@memberjunction/ng-core-entity-forms 6.1.3 → 6.2.0-edge.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +22 -0
  2. package/dist/lib/custom/MLModels/ml-model-form.component.d.ts +27 -0
  3. package/dist/lib/custom/MLModels/ml-model-form.component.d.ts.map +1 -0
  4. package/dist/lib/custom/MLModels/ml-model-form.component.js +193 -0
  5. package/dist/lib/custom/MLModels/ml-model-form.component.js.map +1 -0
  6. package/dist/lib/custom/MLModels/ml-model-view-models.d.ts +44 -0
  7. package/dist/lib/custom/MLModels/ml-model-view-models.d.ts.map +1 -0
  8. package/dist/lib/custom/MLModels/ml-model-view-models.js +208 -0
  9. package/dist/lib/custom/MLModels/ml-model-view-models.js.map +1 -0
  10. package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts +76 -0
  11. package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts.map +1 -0
  12. package/dist/lib/custom/MLModels/ps-model-detail.component.js +693 -0
  13. package/dist/lib/custom/MLModels/ps-model-detail.component.js.map +1 -0
  14. package/dist/lib/custom/RecordProcesses/record-process-form.component.d.ts +27 -7
  15. package/dist/lib/custom/RecordProcesses/record-process-form.component.d.ts.map +1 -1
  16. package/dist/lib/custom/RecordProcesses/record-process-form.component.js +496 -19
  17. package/dist/lib/custom/RecordProcesses/record-process-form.component.js.map +1 -1
  18. package/dist/lib/custom/custom-forms.module.d.ts +32 -30
  19. package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
  20. package/dist/lib/custom/custom-forms.module.js +21 -4
  21. package/dist/lib/custom/custom-forms.module.js.map +1 -1
  22. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.d.ts.map +1 -1
  23. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js +62 -26
  24. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js.map +1 -1
  25. package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.d.ts.map +1 -1
  26. package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js +33 -15
  27. package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js.map +1 -1
  28. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.d.ts.map +1 -1
  29. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +100 -82
  30. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
  31. package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.js +24 -20
  32. package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.js.map +1 -1
  33. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.d.ts +10 -0
  34. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.d.ts.map +1 -0
  35. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js +122 -0
  36. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js.map +1 -0
  37. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.d.ts +10 -0
  38. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.d.ts.map +1 -0
  39. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.js +125 -0
  40. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.js.map +1 -0
  41. package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.d.ts.map +1 -1
  42. package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.js +23 -5
  43. package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.js.map +1 -1
  44. package/dist/lib/generated/Entities/MJProcessRunDetail/mjprocessrundetail.form.component.d.ts.map +1 -1
  45. package/dist/lib/generated/Entities/MJProcessRunDetail/mjprocessrundetail.form.component.js +25 -6
  46. package/dist/lib/generated/Entities/MJProcessRunDetail/mjprocessrundetail.form.component.js.map +1 -1
  47. package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.d.ts.map +1 -1
  48. package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.js +11 -15
  49. package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.js.map +1 -1
  50. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.d.ts.map +1 -1
  51. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js +43 -7
  52. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js.map +1 -1
  53. package/dist/lib/generated/Entities/MJWebSearchProvider/mjwebsearchprovider.form.component.d.ts +10 -0
  54. package/dist/lib/generated/Entities/MJWebSearchProvider/mjwebsearchprovider.form.component.d.ts.map +1 -0
  55. package/dist/lib/generated/Entities/MJWebSearchProvider/mjwebsearchprovider.form.component.js +78 -0
  56. package/dist/lib/generated/Entities/MJWebSearchProvider/mjwebsearchprovider.form.component.js.map +1 -0
  57. package/dist/lib/generated/generated-forms.module.d.ts +240 -237
  58. package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
  59. package/dist/lib/generated/generated-forms.module.js +11 -2
  60. package/dist/lib/generated/generated-forms.module.js.map +1 -1
  61. package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts +95 -0
  62. package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts.map +1 -1
  63. package/dist/lib/panels/model-predictions/model-prediction.logic.js +173 -0
  64. package/dist/lib/panels/model-predictions/model-prediction.logic.js.map +1 -1
  65. package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts +57 -2
  66. package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts.map +1 -1
  67. package/dist/lib/panels/model-predictions/model-prediction.panel.js +555 -64
  68. package/dist/lib/panels/model-predictions/model-prediction.panel.js.map +1 -1
  69. package/dist/public-api.d.ts +4 -0
  70. package/dist/public-api.d.ts.map +1 -1
  71. package/dist/public-api.js +4 -0
  72. package/dist/public-api.js.map +1 -1
  73. package/package.json +42 -41
@@ -7,6 +7,7 @@
7
7
  * or domain-specific — it operates purely on numbers, strings, and the model's
8
8
  * generic `ProblemType` / `FeatureImportance` JSON.
9
9
  */
10
+ import { OutcomeBand, OutcomeConfig } from '@memberjunction/predictive-studio-core';
10
11
  /**
11
12
  * The neutral tercile a numeric prediction falls into. No moral direction is
12
13
  * implied — `low`/`mid`/`high` describe position on the value axis only.
@@ -66,4 +67,98 @@ export declare function resolveLabel(targetVariable: string | null, targetColumn
66
67
  export declare function parseDrivers(featureImportanceJson: string | null): PredictionDriver[];
67
68
  /** Format a last-scored timestamp to a short date, or null when absent/invalid. */
68
69
  export declare function formatLastScored(lastScoredAt: Date | string | null): string | null;
70
+ /**
71
+ * A resolved historical prediction row from `MJ: Process Run Details` for an entity record.
72
+ */
73
+ export interface PredictionHistoryItem {
74
+ /** The MJ: Process Run Details primary key ID */
75
+ id: string;
76
+ /** The parent Process Run ID */
77
+ processRunId: string;
78
+ /** Model ID if resolved from payload or model lookup */
79
+ modelId: string | null;
80
+ /** Resolved model name (e.g. "Member Churn Risk" or "LatePaymentOutcome") */
81
+ modelName: string;
82
+ /** Resolved pipeline & version string (e.g. "Pipeline v1") */
83
+ provenance: string;
84
+ /** Target variable / label */
85
+ target: string;
86
+ /** Problem type: classification or regression */
87
+ problemType: ModelProblemType;
88
+ /** Primary numeric value / score */
89
+ numericValue: number | null;
90
+ /** Class label if classification */
91
+ predictedClass: string | null;
92
+ /** Formatted display value (e.g. "88%", "Late", "1,240.5") */
93
+ displayValue: string;
94
+ /** True if 0–1 probability we can gauge/badge */
95
+ isProbability: boolean;
96
+ /** Neutral band: 'low' | 'mid' | 'high' */
97
+ band: PredictionBand | null;
98
+ /** Resolved semantic status band from outcomeConfig */
99
+ statusBand: OutcomeBand | null;
100
+ /** Human-readable status label (e.g. "Low Risk", "High") */
101
+ statusLabel: string | null;
102
+ /** Semantic badge color ('green' | 'amber' | 'red' | 'blue' | 'gray') */
103
+ badgeColor: 'green' | 'amber' | 'red' | 'blue' | 'gray';
104
+ /** Icon class if specified in band/style */
105
+ badgeIcon: string | null;
106
+ /** Execution status: 'Succeeded' | 'Failed' | 'Pending' | 'Skipped' */
107
+ status: string;
108
+ /** When processing completed */
109
+ completedAt: Date | null;
110
+ /** Formatted date/time for history display */
111
+ formattedTime: string;
112
+ /** Drivers if available in payload */
113
+ drivers: PredictionDriver[];
114
+ /** Error message if Failed */
115
+ errorMessage: string | null;
116
+ /** Full raw payload object for JSON inspection */
117
+ rawPayload: Record<string, unknown> | null;
118
+ }
119
+ /** Summary descriptor of a model represented in prediction history. */
120
+ export interface ModelHistorySummary {
121
+ modelId: string;
122
+ modelName: string;
123
+ count: number;
124
+ }
125
+ /** Input contract for parsing a Process Run Detail record. */
126
+ export interface RawProcessRunDetail {
127
+ ID: string;
128
+ ProcessRunID: string;
129
+ Status: string;
130
+ CompletedAt: Date | string | null;
131
+ ResultPayload: string | null;
132
+ ErrorMessage: string | null;
133
+ }
134
+ /** Model metadata lookup contract for decorating history items. */
135
+ export interface HistoryModelMetadata {
136
+ Name?: string;
137
+ Pipeline?: string;
138
+ Version?: number;
139
+ ProblemType?: string;
140
+ TargetVariable?: string;
141
+ Lineage?: string | null;
142
+ outcomeConfig?: OutcomeConfig | null;
143
+ }
144
+ /**
145
+ * Format a history completion timestamp with date and time.
146
+ */
147
+ export declare function formatHistoryTimestamp(date: Date | string | null): string;
148
+ /**
149
+ * Parse an array of drivers from payload driver shapes (array of { feature, value } or map).
150
+ */
151
+ export declare function parsePayloadDrivers(rawDrivers: unknown): PredictionDriver[];
152
+ /**
153
+ * Parse a raw `MJ: Process Run Details` row into a decorated {@link PredictionHistoryItem}.
154
+ */
155
+ export declare function parseHistoryItem(detail: RawProcessRunDetail, modelLookup?: Map<string, HistoryModelMetadata>): PredictionHistoryItem;
156
+ /**
157
+ * Filter prediction history by a selected model ID (or return all when null / 'ALL').
158
+ */
159
+ export declare function filterHistoryByModel(history: PredictionHistoryItem[], selectedModelId: string | null): PredictionHistoryItem[];
160
+ /**
161
+ * Aggregate unique models from prediction history for multi-model tabs / filters.
162
+ */
163
+ export declare function getDistinctModelsFromHistory(history: PredictionHistoryItem[]): ModelHistorySummary[];
69
164
  //# sourceMappingURL=model-prediction.logic.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-prediction.logic.d.ts","sourceRoot":"","sources":["../../../../src/lib/panels/model-predictions/model-prediction.logic.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAEpD,sDAAsD;AACtD,MAAM,MAAM,gBAAgB,GAAG,gBAAgB,GAAG,YAAY,CAAC;AAE/D,4DAA4D;AAC5D,MAAM,WAAW,gBAAgB;IAC7B,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,2DAA2D;AAC3D,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC;AAEtE,mEAAmE;AACnE,eAAO,MAAM,WAAW,IAAI,CAAC;AAE7B;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAStD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,mBAAmB,CASpG;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAKrD;AAED,uEAAuE;AACvE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAWxG;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAM/F;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,GAAG,gBAAgB,EAAE,CAwBrF;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CASlF"}
1
+ {"version":3,"file":"model-prediction.logic.d.ts","sourceRoot":"","sources":["../../../../src/lib/panels/model-predictions/model-prediction.logic.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@
7
7
  * or domain-specific — it operates purely on numbers, strings, and the model's
8
8
  * generic `ProblemType` / `FeatureImportance` JSON.
9
9
  */
10
+ import { resolveOutcomeConfig, resolveOutcomeStyle, resolveScoreBand, } from '@memberjunction/predictive-studio-core';
10
11
  /** Maximum number of feature-importance drivers shown per card. */
11
12
  export const MAX_DRIVERS = 5;
12
13
  /**
@@ -127,4 +128,176 @@ export function formatLastScored(lastScoredAt) {
127
128
  }
128
129
  return d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
129
130
  }
131
+ /**
132
+ * Format a history completion timestamp with date and time.
133
+ */
134
+ export function formatHistoryTimestamp(date) {
135
+ if (!date)
136
+ return '—';
137
+ const d = date instanceof Date ? date : new Date(date);
138
+ if (isNaN(d.getTime()))
139
+ return '—';
140
+ return d.toLocaleString(undefined, {
141
+ month: 'short',
142
+ day: 'numeric',
143
+ year: 'numeric',
144
+ hour: 'numeric',
145
+ minute: '2-digit',
146
+ });
147
+ }
148
+ /**
149
+ * Parse an array of drivers from payload driver shapes (array of { feature, value } or map).
150
+ */
151
+ export function parsePayloadDrivers(rawDrivers) {
152
+ if (!rawDrivers)
153
+ return [];
154
+ if (Array.isArray(rawDrivers)) {
155
+ const entries = rawDrivers
156
+ .map((item) => {
157
+ if (!item || typeof item !== 'object')
158
+ return null;
159
+ const rec = item;
160
+ const name = typeof rec['feature'] === 'string' ? rec['feature'] : (typeof rec['name'] === 'string' ? rec['name'] : '');
161
+ const val = toNumber(rec['value'] ?? rec['importance']);
162
+ if (!name || val == null)
163
+ return null;
164
+ return { name, importance: Math.abs(val) };
165
+ })
166
+ .filter((d) => d != null && d.importance > 0)
167
+ .sort((a, b) => b.importance - a.importance)
168
+ .slice(0, MAX_DRIVERS);
169
+ const max = entries.length > 0 ? entries[0].importance : 0;
170
+ return entries.map(d => ({
171
+ ...d,
172
+ relativePct: max > 0 ? Math.round((d.importance / max) * 100) : 0,
173
+ }));
174
+ }
175
+ if (typeof rawDrivers === 'object') {
176
+ return parseDrivers(JSON.stringify(rawDrivers));
177
+ }
178
+ return [];
179
+ }
180
+ /**
181
+ * Parse a raw `MJ: Process Run Details` row into a decorated {@link PredictionHistoryItem}.
182
+ */
183
+ export function parseHistoryItem(detail, modelLookup) {
184
+ let rawPayload = null;
185
+ let payloadSection = null;
186
+ if (detail.ResultPayload) {
187
+ try {
188
+ const parsed = JSON.parse(detail.ResultPayload);
189
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
190
+ rawPayload = parsed;
191
+ const outputObj = rawPayload['output'];
192
+ if (outputObj && typeof outputObj === 'object' && !Array.isArray(outputObj)) {
193
+ payloadSection = outputObj;
194
+ }
195
+ else {
196
+ payloadSection = rawPayload;
197
+ }
198
+ }
199
+ }
200
+ catch {
201
+ rawPayload = null;
202
+ payloadSection = null;
203
+ }
204
+ }
205
+ const payloadModelId = typeof payloadSection?.['modelId'] === 'string' ? payloadSection['modelId'] : null;
206
+ const modelMeta = payloadModelId && modelLookup ? modelLookup.get(payloadModelId) : undefined;
207
+ const rawScore = payloadSection?.['score'] ?? payloadSection?.['value'] ?? null;
208
+ const numericScore = toNumber(rawScore);
209
+ const predictedClass = typeof payloadSection?.['class'] === 'string' ? payloadSection['class'] : null;
210
+ const probTypeStr = (typeof payloadSection?.['problemType'] === 'string' ? payloadSection['problemType'] : modelMeta?.ProblemType) ?? '';
211
+ const problemType = probTypeStr.toLowerCase() === 'regression' ? 'regression' : 'classification';
212
+ const kind = valueKind(problemType, numericScore);
213
+ const displayValue = predictedClass ?? formatValue(rawScore, numericScore, kind);
214
+ const targetVar = (typeof payloadSection?.['target'] === 'string' ? payloadSection['target'] : modelMeta?.TargetVariable) ?? '';
215
+ const label = resolveLabel(targetVar, null);
216
+ const modelName = modelMeta?.Name ?? label;
217
+ const provenance = modelMeta?.Pipeline && modelMeta?.Version
218
+ ? `${modelMeta.Pipeline} v${modelMeta.Version}`
219
+ : (modelMeta?.Name ?? 'Predictive Model');
220
+ const completedAt = detail.CompletedAt ? (detail.CompletedAt instanceof Date ? detail.CompletedAt : new Date(detail.CompletedAt)) : null;
221
+ const drivers = parsePayloadDrivers(payloadSection?.['drivers']);
222
+ const rawOutcomeConfig = (payloadSection?.['outcomeConfig'] ?? modelMeta?.outcomeConfig);
223
+ const outcomeConfig = rawOutcomeConfig
224
+ ? resolveOutcomeConfig({ outcomeConfig: rawOutcomeConfig })
225
+ : resolveOutcomeConfig({
226
+ Lineage: modelMeta?.Lineage ?? null,
227
+ TargetVariable: targetVar || modelMeta?.TargetVariable || null,
228
+ ProblemType: probTypeStr || modelMeta?.ProblemType || null,
229
+ });
230
+ let statusBand = null;
231
+ let badgeColor = 'gray';
232
+ let badgeIcon = null;
233
+ let statusLabel = null;
234
+ if (numericScore != null) {
235
+ statusBand = resolveScoreBand(numericScore, outcomeConfig);
236
+ if (statusBand) {
237
+ badgeColor = statusBand.BadgeColor;
238
+ badgeIcon = statusBand.Icon ?? null;
239
+ statusLabel = statusBand.Label;
240
+ }
241
+ }
242
+ else if (predictedClass) {
243
+ const style = resolveOutcomeStyle(predictedClass, outcomeConfig);
244
+ badgeColor = style.BadgeColor;
245
+ badgeIcon = style.Icon ?? null;
246
+ statusLabel = style.DisplayLabel ?? predictedClass;
247
+ }
248
+ return {
249
+ id: detail.ID,
250
+ processRunId: detail.ProcessRunID,
251
+ modelId: payloadModelId,
252
+ modelName,
253
+ provenance,
254
+ target: targetVar || label,
255
+ problemType,
256
+ numericValue: numericScore,
257
+ predictedClass,
258
+ displayValue,
259
+ isProbability: kind === 'probability',
260
+ band: kind === 'probability' && numericScore != null ? bandFor(numericScore) : null,
261
+ statusBand,
262
+ statusLabel,
263
+ badgeColor,
264
+ badgeIcon,
265
+ status: detail.Status || 'Succeeded',
266
+ completedAt,
267
+ formattedTime: formatHistoryTimestamp(completedAt),
268
+ drivers,
269
+ errorMessage: detail.ErrorMessage,
270
+ rawPayload,
271
+ };
272
+ }
273
+ /**
274
+ * Filter prediction history by a selected model ID (or return all when null / 'ALL').
275
+ */
276
+ export function filterHistoryByModel(history, selectedModelId) {
277
+ if (!selectedModelId || selectedModelId === 'ALL') {
278
+ return history;
279
+ }
280
+ return history.filter(item => item.modelId === selectedModelId);
281
+ }
282
+ /**
283
+ * Aggregate unique models from prediction history for multi-model tabs / filters.
284
+ */
285
+ export function getDistinctModelsFromHistory(history) {
286
+ const counts = new Map();
287
+ for (const item of history) {
288
+ const id = item.modelId ?? 'UNKNOWN';
289
+ const existing = counts.get(id);
290
+ if (existing) {
291
+ existing.count += 1;
292
+ }
293
+ else {
294
+ counts.set(id, { modelName: item.modelName, count: 1 });
295
+ }
296
+ }
297
+ return Array.from(counts.entries()).map(([modelId, data]) => ({
298
+ modelId,
299
+ modelName: data.modelName,
300
+ count: data.count,
301
+ }));
302
+ }
130
303
  //# sourceMappingURL=model-prediction.logic.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-prediction.logic.js","sourceRoot":"","sources":["../../../../src/lib/panels/model-predictions/model-prediction.logic.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure, framework-free logic for the entity-agnostic Model Predictions panel.\n *\n * Extracted from the Angular component so the band computation, value\n * formatting, and feature-importance parsing can be unit-tested without\n * standing up Angular or a real entity record. NONE of this is entity-specific\n * or domain-specific — it operates purely on numbers, strings, and the model's\n * generic `ProblemType` / `FeatureImportance` JSON.\n */\n\n/**\n * The neutral tercile a numeric prediction falls into. No moral direction is\n * implied — `low`/`mid`/`high` describe position on the value axis only.\n */\nexport type PredictionBand = 'low' | 'mid' | 'high';\n\n/** Generic problem types a trained model can have. */\nexport type ModelProblemType = 'classification' | 'regression';\n\n/** One normalized feature-importance driver for display. */\nexport interface PredictionDriver {\n /** Raw feature name as the model stored it. */\n name: string;\n /** Importance magnitude (absolute value of the raw contribution). */\n importance: number;\n /** Importance as a 0–100 share of the strongest driver, for the bar width. */\n relativePct: number;\n}\n\n/** How a prediction's primary value should be rendered. */\nexport type PredictionValueKind = 'probability' | 'numeric' | 'class';\n\n/** Maximum number of feature-importance drivers shown per card. */\nexport const MAX_DRIVERS = 5;\n\n/**\n * Coerce a dynamic field value into a finite number, or null when it isn't one.\n */\nexport function toNumber(value: unknown): number | null {\n if (typeof value === 'number') {\n return Number.isFinite(value) ? value : null;\n }\n if (typeof value === 'string' && value.trim() !== '') {\n const n = Number(value);\n return Number.isFinite(n) ? n : null;\n }\n return null;\n}\n\n/**\n * Decide how to render a value given the model's problem type and the value.\n * - regression + numeric → 'numeric'\n * - classification + value in [0,1] → 'probability' (a confidence/score we can gauge)\n * - everything else (a class label, a missing value) → 'class'\n */\nexport function valueKind(problemType: ModelProblemType, numeric: number | null): PredictionValueKind {\n const isRegression = problemType === 'regression';\n if (isRegression && numeric != null) {\n return 'numeric';\n }\n if (!isRegression && numeric != null && numeric >= 0 && numeric <= 1) {\n return 'probability';\n }\n return 'class';\n}\n\n/**\n * Neutral tercile for a 0–1 value. Position on the value axis only — no\n * assumption that high is good or bad. Values are clamped to [0,1].\n */\nexport function bandFor(value: number): PredictionBand {\n const v = Math.max(0, Math.min(1, value));\n if (v < 1 / 3) return 'low';\n if (v < 2 / 3) return 'mid';\n return 'high';\n}\n\n/** Round a 0–1 probability to an integer 0–100 gauge fill, clamped. */\nexport function gaugePct(value: number): number {\n return Math.round(Math.max(0, Math.min(1, value)) * 100);\n}\n\n/**\n * Format the primary value for display:\n * - probability → \"72%\"\n * - numeric (regression) → grouped number, up to 4 decimals\n * - class label → the label string\n * - missing/empty → \"—\" (em dash)\n */\nexport function formatValue(rawValue: unknown, numeric: number | null, kind: PredictionValueKind): string {\n if (kind === 'probability' && numeric != null) {\n return `${gaugePct(numeric)}%`;\n }\n if (kind === 'numeric' && numeric != null) {\n return numeric.toLocaleString(undefined, { maximumFractionDigits: 4 });\n }\n if (rawValue == null || rawValue === '') {\n return '—';\n }\n return String(rawValue);\n}\n\n/**\n * Pick the human label for a prediction: prefer the model's target variable,\n * then the bound column name, then a generic fallback.\n */\nexport function resolveLabel(targetVariable: string | null, targetColumn: string | null): string {\n const target = targetVariable?.trim();\n if (target) return target;\n const col = targetColumn?.trim();\n if (col) return col;\n return 'Prediction';\n}\n\n/**\n * Parse a model's `FeatureImportance` JSON (`Record<string, number>`) into the\n * top-N sorted drivers with relative bar widths. Returns [] on null / invalid /\n * empty input — the caller omits the drivers section cleanly when empty.\n */\nexport function parseDrivers(featureImportanceJson: string | null): PredictionDriver[] {\n if (!featureImportanceJson) {\n return [];\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(featureImportanceJson);\n } catch {\n return [];\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return [];\n }\n const entries = Object.entries(parsed as Record<string, unknown>)\n .map(([name, raw]) => ({ name, importance: Math.abs(toNumber(raw) ?? 0) }))\n .filter(d => d.importance > 0)\n .sort((a, b) => b.importance - a.importance)\n .slice(0, MAX_DRIVERS);\n\n const max = entries.length > 0 ? entries[0].importance : 0;\n return entries.map(d => ({\n ...d,\n relativePct: max > 0 ? Math.round((d.importance / max) * 100) : 0,\n }));\n}\n\n/** Format a last-scored timestamp to a short date, or null when absent/invalid. */\nexport function formatLastScored(lastScoredAt: Date | string | null): string | null {\n if (!lastScoredAt) {\n return null;\n }\n const d = lastScoredAt instanceof Date ? lastScoredAt : new Date(lastScoredAt);\n if (isNaN(d.getTime())) {\n return null;\n }\n return d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });\n}\n"]}
1
+ {"version":3,"file":"model-prediction.logic.js","sourceRoot":"","sources":["../../../../src/lib/panels/model-predictions/model-prediction.logic.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAIH,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,GACnB,MAAM,wCAAwC,CAAC;AAwBhD,mEAAmE;AACnE,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAE7B;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IACjD,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACnD,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,WAA6B,EAAE,OAAsB;IAC3E,MAAM,YAAY,GAAG,WAAW,KAAK,YAAY,CAAC;IAClD,IAAI,YAAY,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,IAAI,CAAC,YAAY,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACnE,OAAO,aAAa,CAAC;IACzB,CAAC;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,KAAa;IACjC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5B,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,QAAQ,CAAC,KAAa;IAClC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,QAAiB,EAAE,OAAsB,EAAE,IAAyB;IAC5F,IAAI,IAAI,KAAK,aAAa,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QAC5C,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC;IACnC,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACxC,OAAO,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,EAAE,qBAAqB,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,KAAK,EAAE,EAAE,CAAC;QACtC,OAAO,GAAG,CAAC;IACf,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,cAA6B,EAAE,YAA2B;IACnF,MAAM,MAAM,GAAG,cAAc,EAAE,IAAI,EAAE,CAAC;IACtC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,GAAG,GAAG,YAAY,EAAE,IAAI,EAAE,CAAC;IACjC,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC;IACpB,OAAO,YAAY,CAAC;AACxB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,qBAAoC;IAC7D,IAAI,CAAC,qBAAqB,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACd,CAAC;IACD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;IACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACjE,OAAO,EAAE,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAiC,CAAC;SAC5D,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;SAC1E,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC;SAC7B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC;SAC3C,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IAE3B,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACrB,GAAG,CAAC;QACJ,WAAW,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;KACpE,CAAC,CAAC,CAAC;AACR,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,gBAAgB,CAAC,YAAkC;IAC/D,IAAI,CAAC,YAAY,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,MAAM,CAAC,GAAG,YAAY,YAAY,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC;IAC/E,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,CAAC,CAAC,kBAAkB,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;AAChG,CAAC;AAgFD;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAA0B;IAC7D,IAAI,CAAC,IAAI;QAAE,OAAO,GAAG,CAAC;IACtB,MAAM,CAAC,GAAG,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IACvD,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QAAE,OAAO,GAAG,CAAC;IACnC,OAAO,CAAC,CAAC,cAAc,CAAC,SAAS,EAAE;QAC/B,KAAK,EAAE,OAAO;QACd,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;KACpB,CAAC,CAAC;AACP,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAmB;IACnD,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAC3B,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,UAAU;aACrB,GAAG,CAAC,CAAC,IAAa,EAAE,EAAE;YACnB,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;YACnD,MAAM,GAAG,GAAG,IAA+B,CAAC;YAC5C,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACxH,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;YACxD,IAAI,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI;gBAAE,OAAO,IAAI,CAAC;YACtC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,CAAC,EAA6C,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC;aACvF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC;aAC3C,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QAE3B,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACrB,GAAG,CAAC;YACJ,WAAW,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SACpE,CAAC,CAAC,CAAC;IACR,CAAC;IACD,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,EAAE,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC5B,MAA2B,EAC3B,WAA+C;IAE/C,IAAI,UAAU,GAAmC,IAAI,CAAC;IACtD,IAAI,cAAc,GAAmC,IAAI,CAAC;IAE1D,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;QACvB,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAChD,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBACjE,UAAU,GAAG,MAAiC,CAAC;gBAC/C,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;gBACvC,IAAI,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC1E,cAAc,GAAG,SAAoC,CAAC;gBAC1D,CAAC;qBAAM,CAAC;oBACJ,cAAc,GAAG,UAAU,CAAC;gBAChC,CAAC;YACL,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACL,UAAU,GAAG,IAAI,CAAC;YAClB,cAAc,GAAG,IAAI,CAAC;QAC1B,CAAC;IACL,CAAC;IAED,MAAM,cAAc,GAAG,OAAO,cAAc,EAAE,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1G,MAAM,SAAS,GAAG,cAAc,IAAI,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE9F,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC,OAAO,CAAC,IAAI,cAAc,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;IAChF,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,cAAc,GAAG,OAAO,cAAc,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEtG,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,EAAE,CAAC,aAAa,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC;IACzI,MAAM,WAAW,GAAqB,WAAW,CAAC,WAAW,EAAE,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC;IAEnH,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,cAAc,IAAI,WAAW,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;IAEjF,MAAM,SAAS,GAAG,CAAC,OAAO,cAAc,EAAE,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,cAAc,CAAC,IAAI,EAAE,CAAC;IAChI,MAAM,KAAK,GAAG,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAE5C,MAAM,SAAS,GAAG,SAAS,EAAE,IAAI,IAAI,KAAK,CAAC;IAC3C,MAAM,UAAU,GAAG,SAAS,EAAE,QAAQ,IAAI,SAAS,EAAE,OAAO;QACxD,CAAC,CAAC,GAAG,SAAS,CAAC,QAAQ,KAAK,SAAS,CAAC,OAAO,EAAE;QAC/C,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,IAAI,kBAAkB,CAAC,CAAC;IAE9C,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,YAAY,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACzI,MAAM,OAAO,GAAG,mBAAmB,CAAC,cAAc,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;IAEjE,MAAM,gBAAgB,GAAG,CAAC,cAAc,EAAE,CAAC,eAAe,CAAC,IAAI,SAAS,EAAE,aAAa,CAA8B,CAAC;IACtH,MAAM,aAAa,GAAG,gBAAgB;QAClC,CAAC,CAAC,oBAAoB,CAAC,EAAE,aAAa,EAAE,gBAAgB,EAAE,CAAC;QAC3D,CAAC,CAAC,oBAAoB,CAAC;YACnB,OAAO,EAAE,SAAS,EAAE,OAAO,IAAI,IAAI;YACnC,cAAc,EAAE,SAAS,IAAI,SAAS,EAAE,cAAc,IAAI,IAAI;YAC9D,WAAW,EAAE,WAAW,IAAI,SAAS,EAAE,WAAW,IAAI,IAAI;SAC7D,CAAC,CAAC;IAEP,IAAI,UAAU,GAAuB,IAAI,CAAC;IAC1C,IAAI,UAAU,GAAgD,MAAM,CAAC;IACrE,IAAI,SAAS,GAAkB,IAAI,CAAC;IACpC,IAAI,WAAW,GAAkB,IAAI,CAAC;IAEtC,IAAI,YAAY,IAAI,IAAI,EAAE,CAAC;QACvB,UAAU,GAAG,gBAAgB,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;QAC3D,IAAI,UAAU,EAAE,CAAC;YACb,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC;YACnC,SAAS,GAAG,UAAU,CAAC,IAAI,IAAI,IAAI,CAAC;YACpC,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC;QACnC,CAAC;IACL,CAAC;SAAM,IAAI,cAAc,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,mBAAmB,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;QACjE,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;QAC9B,SAAS,GAAG,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC;QAC/B,WAAW,GAAG,KAAK,CAAC,YAAY,IAAI,cAAc,CAAC;IACvD,CAAC;IAED,OAAO;QACH,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,OAAO,EAAE,cAAc;QACvB,SAAS;QACT,UAAU;QACV,MAAM,EAAE,SAAS,IAAI,KAAK;QAC1B,WAAW;QACX,YAAY,EAAE,YAAY;QAC1B,cAAc;QACd,YAAY;QACZ,aAAa,EAAE,IAAI,KAAK,aAAa;QACrC,IAAI,EAAE,IAAI,KAAK,aAAa,IAAI,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI;QACnF,UAAU;QACV,WAAW;QACX,UAAU;QACV,SAAS;QACT,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,WAAW;QACpC,WAAW;QACX,aAAa,EAAE,sBAAsB,CAAC,WAAW,CAAC;QAClD,OAAO;QACP,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,UAAU;KACb,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAChC,OAAgC,EAChC,eAA8B;IAE9B,IAAI,CAAC,eAAe,IAAI,eAAe,KAAK,KAAK,EAAE,CAAC;QAChD,OAAO,OAAO,CAAC;IACnB,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,eAAe,CAAC,CAAC;AACpE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,4BAA4B,CAAC,OAAgC;IACzE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAgD,CAAC;IACvE,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,IAAI,SAAS,CAAC;QACrC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,QAAQ,EAAE,CAAC;YACX,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC;QACxB,CAAC;aAAM,CAAC;YACJ,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5D,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1D,OAAO;QACP,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,KAAK,EAAE,IAAI,CAAC,KAAK;KACpB,CAAC,CAAC,CAAC;AACR,CAAC","sourcesContent":["/**\n * Pure, framework-free logic for the entity-agnostic Model Predictions panel.\n *\n * Extracted from the Angular component so the band computation, value\n * formatting, and feature-importance parsing can be unit-tested without\n * standing up Angular or a real entity record. NONE of this is entity-specific\n * or domain-specific — it operates purely on numbers, strings, and the model's\n * generic `ProblemType` / `FeatureImportance` JSON.\n */\n\nimport {\n OutcomeBand,\n OutcomeConfig,\n formatPredictionScore,\n resolveOutcomeConfig,\n resolveOutcomeStyle,\n resolveScoreBand,\n} from '@memberjunction/predictive-studio-core';\n\n/**\n * The neutral tercile a numeric prediction falls into. No moral direction is\n * implied — `low`/`mid`/`high` describe position on the value axis only.\n */\nexport type PredictionBand = 'low' | 'mid' | 'high';\n\n/** Generic problem types a trained model can have. */\nexport type ModelProblemType = 'classification' | 'regression';\n\n/** One normalized feature-importance driver for display. */\nexport interface PredictionDriver {\n /** Raw feature name as the model stored it. */\n name: string;\n /** Importance magnitude (absolute value of the raw contribution). */\n importance: number;\n /** Importance as a 0–100 share of the strongest driver, for the bar width. */\n relativePct: number;\n}\n\n/** How a prediction's primary value should be rendered. */\nexport type PredictionValueKind = 'probability' | 'numeric' | 'class';\n\n/** Maximum number of feature-importance drivers shown per card. */\nexport const MAX_DRIVERS = 5;\n\n/**\n * Coerce a dynamic field value into a finite number, or null when it isn't one.\n */\nexport function toNumber(value: unknown): number | null {\n if (typeof value === 'number') {\n return Number.isFinite(value) ? value : null;\n }\n if (typeof value === 'string' && value.trim() !== '') {\n const n = Number(value);\n return Number.isFinite(n) ? n : null;\n }\n return null;\n}\n\n/**\n * Decide how to render a value given the model's problem type and the value.\n * - regression + numeric → 'numeric'\n * - classification + value in [0,1] → 'probability' (a confidence/score we can gauge)\n * - everything else (a class label, a missing value) → 'class'\n */\nexport function valueKind(problemType: ModelProblemType, numeric: number | null): PredictionValueKind {\n const isRegression = problemType === 'regression';\n if (isRegression && numeric != null) {\n return 'numeric';\n }\n if (!isRegression && numeric != null && numeric >= 0 && numeric <= 1) {\n return 'probability';\n }\n return 'class';\n}\n\n/**\n * Neutral tercile for a 0–1 value. Position on the value axis only — no\n * assumption that high is good or bad. Values are clamped to [0,1].\n */\nexport function bandFor(value: number): PredictionBand {\n const v = Math.max(0, Math.min(1, value));\n if (v < 1 / 3) return 'low';\n if (v < 2 / 3) return 'mid';\n return 'high';\n}\n\n/** Round a 0–1 probability to an integer 0–100 gauge fill, clamped. */\nexport function gaugePct(value: number): number {\n return Math.round(Math.max(0, Math.min(1, value)) * 100);\n}\n\n/**\n * Format the primary value for display:\n * - probability → \"72%\"\n * - numeric (regression) → grouped number, up to 4 decimals\n * - class label → the label string\n * - missing/empty → \"—\" (em dash)\n */\nexport function formatValue(rawValue: unknown, numeric: number | null, kind: PredictionValueKind): string {\n if (kind === 'probability' && numeric != null) {\n return `${gaugePct(numeric)}%`;\n }\n if (kind === 'numeric' && numeric != null) {\n return numeric.toLocaleString(undefined, { maximumFractionDigits: 4 });\n }\n if (rawValue == null || rawValue === '') {\n return '—';\n }\n return String(rawValue);\n}\n\n/**\n * Pick the human label for a prediction: prefer the model's target variable,\n * then the bound column name, then a generic fallback.\n */\nexport function resolveLabel(targetVariable: string | null, targetColumn: string | null): string {\n const target = targetVariable?.trim();\n if (target) return target;\n const col = targetColumn?.trim();\n if (col) return col;\n return 'Prediction';\n}\n\n/**\n * Parse a model's `FeatureImportance` JSON (`Record<string, number>`) into the\n * top-N sorted drivers with relative bar widths. Returns [] on null / invalid /\n * empty input — the caller omits the drivers section cleanly when empty.\n */\nexport function parseDrivers(featureImportanceJson: string | null): PredictionDriver[] {\n if (!featureImportanceJson) {\n return [];\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(featureImportanceJson);\n } catch {\n return [];\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return [];\n }\n const entries = Object.entries(parsed as Record<string, unknown>)\n .map(([name, raw]) => ({ name, importance: Math.abs(toNumber(raw) ?? 0) }))\n .filter(d => d.importance > 0)\n .sort((a, b) => b.importance - a.importance)\n .slice(0, MAX_DRIVERS);\n\n const max = entries.length > 0 ? entries[0].importance : 0;\n return entries.map(d => ({\n ...d,\n relativePct: max > 0 ? Math.round((d.importance / max) * 100) : 0,\n }));\n}\n\n/** Format a last-scored timestamp to a short date, or null when absent/invalid. */\nexport function formatLastScored(lastScoredAt: Date | string | null): string | null {\n if (!lastScoredAt) {\n return null;\n }\n const d = lastScoredAt instanceof Date ? lastScoredAt : new Date(lastScoredAt);\n if (isNaN(d.getTime())) {\n return null;\n }\n return d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });\n}\n\n/**\n * A resolved historical prediction row from `MJ: Process Run Details` for an entity record.\n */\nexport interface PredictionHistoryItem {\n /** The MJ: Process Run Details primary key ID */\n id: string;\n /** The parent Process Run ID */\n processRunId: string;\n /** Model ID if resolved from payload or model lookup */\n modelId: string | null;\n /** Resolved model name (e.g. \"Member Churn Risk\" or \"LatePaymentOutcome\") */\n modelName: string;\n /** Resolved pipeline & version string (e.g. \"Pipeline v1\") */\n provenance: string;\n /** Target variable / label */\n target: string;\n /** Problem type: classification or regression */\n problemType: ModelProblemType;\n /** Primary numeric value / score */\n numericValue: number | null;\n /** Class label if classification */\n predictedClass: string | null;\n /** Formatted display value (e.g. \"88%\", \"Late\", \"1,240.5\") */\n displayValue: string;\n /** True if 0–1 probability we can gauge/badge */\n isProbability: boolean;\n /** Neutral band: 'low' | 'mid' | 'high' */\n band: PredictionBand | null;\n /** Resolved semantic status band from outcomeConfig */\n statusBand: OutcomeBand | null;\n /** Human-readable status label (e.g. \"Low Risk\", \"High\") */\n statusLabel: string | null;\n /** Semantic badge color ('green' | 'amber' | 'red' | 'blue' | 'gray') */\n badgeColor: 'green' | 'amber' | 'red' | 'blue' | 'gray';\n /** Icon class if specified in band/style */\n badgeIcon: string | null;\n /** Execution status: 'Succeeded' | 'Failed' | 'Pending' | 'Skipped' */\n status: string;\n /** When processing completed */\n completedAt: Date | null;\n /** Formatted date/time for history display */\n formattedTime: string;\n /** Drivers if available in payload */\n drivers: PredictionDriver[];\n /** Error message if Failed */\n errorMessage: string | null;\n /** Full raw payload object for JSON inspection */\n rawPayload: Record<string, unknown> | null;\n}\n\n/** Summary descriptor of a model represented in prediction history. */\nexport interface ModelHistorySummary {\n modelId: string;\n modelName: string;\n count: number;\n}\n\n/** Input contract for parsing a Process Run Detail record. */\nexport interface RawProcessRunDetail {\n ID: string;\n ProcessRunID: string;\n Status: string;\n CompletedAt: Date | string | null;\n ResultPayload: string | null;\n ErrorMessage: string | null;\n}\n\n/** Model metadata lookup contract for decorating history items. */\nexport interface HistoryModelMetadata {\n Name?: string;\n Pipeline?: string;\n Version?: number;\n ProblemType?: string;\n TargetVariable?: string;\n Lineage?: string | null;\n outcomeConfig?: OutcomeConfig | null;\n}\n\n/**\n * Format a history completion timestamp with date and time.\n */\nexport function formatHistoryTimestamp(date: Date | string | null): string {\n if (!date) return '—';\n const d = date instanceof Date ? date : new Date(date);\n if (isNaN(d.getTime())) return '—';\n return d.toLocaleString(undefined, {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n });\n}\n\n/**\n * Parse an array of drivers from payload driver shapes (array of { feature, value } or map).\n */\nexport function parsePayloadDrivers(rawDrivers: unknown): PredictionDriver[] {\n if (!rawDrivers) return [];\n if (Array.isArray(rawDrivers)) {\n const entries = rawDrivers\n .map((item: unknown) => {\n if (!item || typeof item !== 'object') return null;\n const rec = item as Record<string, unknown>;\n const name = typeof rec['feature'] === 'string' ? rec['feature'] : (typeof rec['name'] === 'string' ? rec['name'] : '');\n const val = toNumber(rec['value'] ?? rec['importance']);\n if (!name || val == null) return null;\n return { name, importance: Math.abs(val) };\n })\n .filter((d): d is { name: string; importance: number } => d != null && d.importance > 0)\n .sort((a, b) => b.importance - a.importance)\n .slice(0, MAX_DRIVERS);\n\n const max = entries.length > 0 ? entries[0].importance : 0;\n return entries.map(d => ({\n ...d,\n relativePct: max > 0 ? Math.round((d.importance / max) * 100) : 0,\n }));\n }\n if (typeof rawDrivers === 'object') {\n return parseDrivers(JSON.stringify(rawDrivers));\n }\n return [];\n}\n\n/**\n * Parse a raw `MJ: Process Run Details` row into a decorated {@link PredictionHistoryItem}.\n */\nexport function parseHistoryItem(\n detail: RawProcessRunDetail,\n modelLookup?: Map<string, HistoryModelMetadata>,\n): PredictionHistoryItem {\n let rawPayload: Record<string, unknown> | null = null;\n let payloadSection: Record<string, unknown> | null = null;\n\n if (detail.ResultPayload) {\n try {\n const parsed = JSON.parse(detail.ResultPayload);\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n rawPayload = parsed as Record<string, unknown>;\n const outputObj = rawPayload['output'];\n if (outputObj && typeof outputObj === 'object' && !Array.isArray(outputObj)) {\n payloadSection = outputObj as Record<string, unknown>;\n } else {\n payloadSection = rawPayload;\n }\n }\n } catch {\n rawPayload = null;\n payloadSection = null;\n }\n }\n\n const payloadModelId = typeof payloadSection?.['modelId'] === 'string' ? payloadSection['modelId'] : null;\n const modelMeta = payloadModelId && modelLookup ? modelLookup.get(payloadModelId) : undefined;\n\n const rawScore = payloadSection?.['score'] ?? payloadSection?.['value'] ?? null;\n const numericScore = toNumber(rawScore);\n const predictedClass = typeof payloadSection?.['class'] === 'string' ? payloadSection['class'] : null;\n\n const probTypeStr = (typeof payloadSection?.['problemType'] === 'string' ? payloadSection['problemType'] : modelMeta?.ProblemType) ?? '';\n const problemType: ModelProblemType = probTypeStr.toLowerCase() === 'regression' ? 'regression' : 'classification';\n\n const kind = valueKind(problemType, numericScore);\n const displayValue = predictedClass ?? formatValue(rawScore, numericScore, kind);\n\n const targetVar = (typeof payloadSection?.['target'] === 'string' ? payloadSection['target'] : modelMeta?.TargetVariable) ?? '';\n const label = resolveLabel(targetVar, null);\n\n const modelName = modelMeta?.Name ?? label;\n const provenance = modelMeta?.Pipeline && modelMeta?.Version\n ? `${modelMeta.Pipeline} v${modelMeta.Version}`\n : (modelMeta?.Name ?? 'Predictive Model');\n\n const completedAt = detail.CompletedAt ? (detail.CompletedAt instanceof Date ? detail.CompletedAt : new Date(detail.CompletedAt)) : null;\n const drivers = parsePayloadDrivers(payloadSection?.['drivers']);\n\n const rawOutcomeConfig = (payloadSection?.['outcomeConfig'] ?? modelMeta?.outcomeConfig) as OutcomeConfig | undefined;\n const outcomeConfig = rawOutcomeConfig\n ? resolveOutcomeConfig({ outcomeConfig: rawOutcomeConfig })\n : resolveOutcomeConfig({\n Lineage: modelMeta?.Lineage ?? null,\n TargetVariable: targetVar || modelMeta?.TargetVariable || null,\n ProblemType: probTypeStr || modelMeta?.ProblemType || null,\n });\n\n let statusBand: OutcomeBand | null = null;\n let badgeColor: 'green' | 'amber' | 'red' | 'blue' | 'gray' = 'gray';\n let badgeIcon: string | null = null;\n let statusLabel: string | null = null;\n\n if (numericScore != null) {\n statusBand = resolveScoreBand(numericScore, outcomeConfig);\n if (statusBand) {\n badgeColor = statusBand.BadgeColor;\n badgeIcon = statusBand.Icon ?? null;\n statusLabel = statusBand.Label;\n }\n } else if (predictedClass) {\n const style = resolveOutcomeStyle(predictedClass, outcomeConfig);\n badgeColor = style.BadgeColor;\n badgeIcon = style.Icon ?? null;\n statusLabel = style.DisplayLabel ?? predictedClass;\n }\n\n return {\n id: detail.ID,\n processRunId: detail.ProcessRunID,\n modelId: payloadModelId,\n modelName,\n provenance,\n target: targetVar || label,\n problemType,\n numericValue: numericScore,\n predictedClass,\n displayValue,\n isProbability: kind === 'probability',\n band: kind === 'probability' && numericScore != null ? bandFor(numericScore) : null,\n statusBand,\n statusLabel,\n badgeColor,\n badgeIcon,\n status: detail.Status || 'Succeeded',\n completedAt,\n formattedTime: formatHistoryTimestamp(completedAt),\n drivers,\n errorMessage: detail.ErrorMessage,\n rawPayload,\n };\n}\n\n/**\n * Filter prediction history by a selected model ID (or return all when null / 'ALL').\n */\nexport function filterHistoryByModel(\n history: PredictionHistoryItem[],\n selectedModelId: string | null,\n): PredictionHistoryItem[] {\n if (!selectedModelId || selectedModelId === 'ALL') {\n return history;\n }\n return history.filter(item => item.modelId === selectedModelId);\n}\n\n/**\n * Aggregate unique models from prediction history for multi-model tabs / filters.\n */\nexport function getDistinctModelsFromHistory(history: PredictionHistoryItem[]): ModelHistorySummary[] {\n const counts = new Map<string, { modelName: string; count: number }>();\n for (const item of history) {\n const id = item.modelId ?? 'UNKNOWN';\n const existing = counts.get(id);\n if (existing) {\n existing.count += 1;\n } else {\n counts.set(id, { modelName: item.modelName, count: 1 });\n }\n }\n return Array.from(counts.entries()).map(([modelId, data]) => ({\n modelId,\n modelName: data.modelName,\n count: data.count,\n }));\n}\n"]}
@@ -1,6 +1,8 @@
1
1
  import { OnInit } from '@angular/core';
2
2
  import { BaseFormPanel } from '@memberjunction/ng-base-forms';
3
- import { PredictionBand, PredictionDriver } from './model-prediction.logic';
3
+ import { MJMLModelEntity } from '@memberjunction/core-entities';
4
+ import { OutcomeBand } from '@memberjunction/predictive-studio-core';
5
+ import { ModelHistorySummary, PredictionBand, PredictionDriver, PredictionHistoryItem } from './model-prediction.logic';
4
6
  import * as i0 from "@angular/core";
5
7
  /**
6
8
  * A fully-resolved, entity-agnostic prediction card view-model. One per active
@@ -9,6 +11,8 @@ import * as i0 from "@angular/core";
9
11
  export interface PredictionCard {
10
12
  /** Binding ID — used as the @for track key. */
11
13
  bindingId: string;
14
+ /** Model ID — used to cross-link with prediction history. */
15
+ modelId: string;
12
16
  /** Human label for the prediction (model target → bound column → fallback). */
13
17
  label: string;
14
18
  /** True when the model is a 0–1 probability we can render as a gauge. */
@@ -23,6 +27,14 @@ export interface PredictionCard {
23
27
  gaugePct: number;
24
28
  /** Neutral band for the gauge segment styling (only meaningful when isProbability). */
25
29
  band: PredictionBand | null;
30
+ /** Resolved semantic status band from outcomeConfig */
31
+ statusBand: OutcomeBand | null;
32
+ /** Human-readable status label (e.g. "Low Risk", "High") */
33
+ statusLabel: string | null;
34
+ /** Semantic badge color: 'green' | 'amber' | 'red' | 'blue' | 'gray' */
35
+ badgeColor: 'green' | 'amber' | 'red' | 'blue' | 'gray';
36
+ /** FontAwesome icon class (e.g. 'fa-circle-check', 'fa-triangle-exclamation') */
37
+ badgeIcon: string | null;
26
38
  /** Top feature-importance drivers, or empty when unavailable. */
27
39
  drivers: PredictionDriver[];
28
40
  /** Provenance: "Pipeline Name v3". */
@@ -48,25 +60,68 @@ export interface PredictionCard {
48
60
  * (composition) by binding `[Record]` + `[FormComponent]`.
49
61
  */
50
62
  export declare class ModelPredictionPanel extends BaseFormPanel implements OnInit {
63
+ private cdr;
51
64
  /** The resolved cards to render. Empty → panel renders nothing. */
52
65
  Cards: PredictionCard[];
53
66
  /** True once the binding lookup has completed (success or empty). */
54
67
  Loaded: boolean;
68
+ /** Resolved models by ID for lineage and history decoration. */
69
+ modelsById: Map<string, MJMLModelEntity>;
70
+ /** Historical prediction runs for this record across models. */
71
+ HistoryItems: PredictionHistoryItem[];
72
+ /** Loading flag for historical predictions lookup. */
73
+ LoadingHistory: boolean;
74
+ /** Whether the prediction history section is expanded in the template. */
75
+ ShowHistorySection: boolean;
76
+ /** Selected model ID for history filtering (null = all models). */
77
+ SelectedModelId: string | null;
78
+ /** Expanded history item ID for in-place inspection of payload & drivers. */
79
+ ExpandedHistoryItemId: string | null;
55
80
  /** Entity-ID we last loaded cards for, to avoid redundant lookups. */
56
81
  private loadedForEntityId;
57
82
  ngOnInit(): Promise<void>;
58
- /** True when there is at least one card to show — gates the whole template. */
83
+ /** True when there is at least one card or history item to show — gates the whole template. */
59
84
  get HasPredictions(): boolean;
85
+ /** Filtered history items based on currently selected model. */
86
+ get FilteredHistory(): PredictionHistoryItem[];
87
+ /** Distinct models in prediction history with counts. */
88
+ get ModelSummaries(): ModelHistorySummary[];
60
89
  /**
61
90
  * Look up active scoring bindings for THIS record's entity and build a card
62
91
  * per binding. Idempotent + cheap: a single RunView (cached by the server),
63
92
  * skipped entirely when we've already loaded for this entity.
64
93
  */
65
94
  private loadCards;
95
+ /**
96
+ * Load historical prediction runs for this specific record across all models.
97
+ */
98
+ LoadHistory(): Promise<void>;
99
+ /**
100
+ * Select a model ID filter for history (null = all models).
101
+ */
102
+ SelectModelFilter(modelId: string | null): void;
103
+ /**
104
+ * Toggle the prediction history section.
105
+ */
106
+ ToggleHistorySection(): void;
107
+ /**
108
+ * Focus prediction history on a specific model from a card action.
109
+ */
110
+ OpenHistoryForModel(modelId: string, event?: MouseEvent): void;
111
+ /**
112
+ * Toggle inline inspection drawer for a prediction history row.
113
+ */
114
+ ToggleHistoryDetails(item: PredictionHistoryItem, event?: MouseEvent): void;
115
+ /**
116
+ * Drill down into the underlying MJ: Process Run Details record in Explorer.
117
+ */
118
+ DrilldownToPredictionRecord(item: PredictionHistoryItem, event?: MouseEvent): void;
66
119
  /** Active scoring bindings whose target entity is the current record's entity. */
67
120
  private loadBindingsForEntity;
68
121
  /** Load the distinct models referenced by the bindings, keyed by model ID. */
69
122
  private loadModelsForBindings;
123
+ /** Ensure models found in process run detail payloads are loaded for metadata decoration. */
124
+ private ensureModelsLoadedForHistory;
70
125
  /** Map each binding (+ its model) to a display card. Skips bindings whose model is missing. */
71
126
  private buildCards;
72
127
  /** Build one card from a binding + model + the record's bound-column value. */
@@ -1 +1 @@
1
- {"version":3,"file":"model-prediction.panel.d.ts","sourceRoot":"","sources":["../../../../src/lib/panels/model-predictions/model-prediction.panel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAG9D,OAAO,EACH,cAAc,EACd,gBAAgB,EASnB,MAAM,0BAA0B,CAAC;;AAElC;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC3B,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,aAAa,EAAE,OAAO,CAAC;IACvB,8DAA8D;IAC9D,SAAS,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,OAAO,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,YAAY,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC;IACjB,uFAAuF;IACvF,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IAC5B,iEAAiE;IACjE,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAea,oBAAqB,SAAQ,aAAc,YAAW,MAAM;IACrE,mEAAmE;IAC5D,KAAK,EAAE,cAAc,EAAE,CAAM;IACpC,qEAAqE;IAC9D,MAAM,UAAS;IACtB,sEAAsE;IACtE,OAAO,CAAC,iBAAiB,CAAuB;IAEnC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,+EAA+E;IAC/E,IAAW,cAAc,IAAI,OAAO,CAEnC;IAED;;;;OAIG;YACW,SAAS;IA4BvB,kFAAkF;YACpE,qBAAqB;IAkBnC,8EAA8E;YAChE,qBAAqB;IA4BnC,+FAA+F;IAC/F,OAAO,CAAC,UAAU;IAelB,+EAA+E;IAC/E,OAAO,CAAC,SAAS;IAsBjB,kFAAkF;IAClF,OAAO,CAAC,OAAO;IAKf,+EAA+E;IAC/E,OAAO,CAAC,WAAW;yCAhJV,oBAAoB;2CAApB,oBAAoB;CAmJhC;AAED,uEAAuE;AACvE,wBAAgB,wBAAwB,IAAI,IAAI,CAAuB"}
1
+ {"version":3,"file":"model-prediction.panel.d.ts","sourceRoot":"","sources":["../../../../src/lib/panels/model-predictions/model-prediction.panel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,MAAM,EAAU,MAAM,eAAe,CAAC;AAE7E,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D,OAAO,EAAE,eAAe,EAA2D,MAAM,+BAA+B,CAAC;AACzH,OAAO,EACH,WAAW,EAId,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACH,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EAYxB,MAAM,0BAA0B,CAAC;;AAElC;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC3B,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,aAAa,EAAE,OAAO,CAAC;IACvB,8DAA8D;IAC9D,SAAS,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,OAAO,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,YAAY,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC;IACjB,uFAAuF;IACvF,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IAC5B,uDAAuD;IACvD,UAAU,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/B,4DAA4D;IAC5D,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,wEAAwE;IACxE,UAAU,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACxD,iFAAiF;IACjF,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,iEAAiE;IACjE,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAea,oBAAqB,SAAQ,aAAc,YAAW,MAAM;IACrE,OAAO,CAAC,GAAG,CAA6B;IAExC,mEAAmE;IAC5D,KAAK,EAAE,cAAc,EAAE,CAAM;IACpC,qEAAqE;IAC9D,MAAM,UAAS;IACtB,gEAAgE;IACzD,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAa;IAC5D,gEAAgE;IACzD,YAAY,EAAE,qBAAqB,EAAE,CAAM;IAClD,sDAAsD;IAC/C,cAAc,UAAS;IAC9B,0EAA0E;IACnE,kBAAkB,UAAS;IAClC,mEAAmE;IAC5D,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC7C,6EAA6E;IACtE,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAQ;IACnD,sEAAsE;IACtE,OAAO,CAAC,iBAAiB,CAAuB;IAEnC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,+FAA+F;IAC/F,IAAW,cAAc,IAAI,OAAO,CAEnC;IAED,gEAAgE;IAChE,IAAW,eAAe,IAAI,qBAAqB,EAAE,CAEpD;IAED,yDAAyD;IACzD,IAAW,cAAc,IAAI,mBAAmB,EAAE,CAEjD;IAED;;;;OAIG;YACW,SAAS;IA+BvB;;OAEG;IACU,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAyDzC;;OAEG;IACI,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAKtD;;OAEG;IACI,oBAAoB,IAAI,IAAI;IAQnC;;OAEG;IACI,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,IAAI;IAUrE;;OAEG;IACI,oBAAoB,CAAC,IAAI,EAAE,qBAAqB,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,IAAI;IAMlF;;OAEG;IACI,2BAA2B,CAAC,IAAI,EAAE,qBAAqB,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,IAAI;IAYzF,kFAAkF;YACpE,qBAAqB;IAkBnC,8EAA8E;YAChE,qBAAqB;IA4BnC,6FAA6F;YAC/E,4BAA4B;IAsC1C,+FAA+F;IAC/F,OAAO,CAAC,UAAU;IAelB,+EAA+E;IAC/E,OAAO,CAAC,SAAS;IAoDjB,kFAAkF;IAClF,OAAO,CAAC,OAAO;IAKf,+EAA+E;IAC/E,OAAO,CAAC,WAAW;yCApWV,oBAAoB;2CAApB,oBAAoB;CAuWhC;AAED,uEAAuE;AACvE,wBAAgB,wBAAwB,IAAI,IAAI,CAAuB"}