@trillboards/edge-core 0.2.2 → 0.3.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.
@@ -0,0 +1,164 @@
1
+ /**
2
+ * MemoryAttenuationManager — Monitors V8 heap and OS memory, applies tiered
3
+ * shedding to keep edge devices stable under pressure.
4
+ *
5
+ * Port of CTV agent's MemoryAttenuationManager.kt, adapted for the V8 heap
6
+ * model. Uses `process.memoryUsage()` for heap metrics and `os.freemem()` /
7
+ * `os.totalmem()` for system-level awareness.
8
+ *
9
+ * Tiers (based on heap usage percentage = heapUsed / heapTotal):
10
+ * GREEN — Normal operation, all systems active
11
+ * YELLOW — >70% heap — disable cloud inference
12
+ * ORANGE — >80% heap — disable federated learning, reduce FPS
13
+ * RED — >90% heap — shed lowest-priority models (one per cycle)
14
+ * CRITICAL — >95% heap — camera-only emergency mode, force GC
15
+ *
16
+ * Hysteresis prevents oscillation: a tier is only restored when usage drops
17
+ * a configurable percentage (default 15%) below the threshold that triggered
18
+ * escalation. For example, YELLOW triggers at 70% but only restores to GREEN
19
+ * when usage falls below 55%.
20
+ */
21
+ /// <reference types="node" />
22
+ import { EventEmitter } from 'events';
23
+ export declare enum MemoryTier {
24
+ GREEN = "GREEN",
25
+ YELLOW = "YELLOW",
26
+ ORANGE = "ORANGE",
27
+ RED = "RED",
28
+ CRITICAL = "CRITICAL"
29
+ }
30
+ export interface MemorySnapshot {
31
+ heapUsedMb: number;
32
+ heapTotalMb: number;
33
+ heapUsedPercent: number;
34
+ rssUsedMb: number;
35
+ osFreeMemMb: number;
36
+ osTotalMemMb: number;
37
+ osUsedPercent: number;
38
+ tier: MemoryTier;
39
+ timestamp: number;
40
+ }
41
+ export interface AttenuationAction {
42
+ tier: MemoryTier;
43
+ action: string;
44
+ timestamp: number;
45
+ }
46
+ export interface AttenuationCallbacks {
47
+ onDisableCloudInference: () => void;
48
+ onEnableCloudInference: () => void;
49
+ onDisableFederatedLearning: () => void;
50
+ onEnableFederatedLearning: () => void;
51
+ onReduceSensingFps: (targetFps: number) => void;
52
+ onRestoreSensingFps: (targetFps: number) => void;
53
+ onShedModel: (modelName: string) => void;
54
+ onRestoreModel: (modelName: string) => void;
55
+ onForceGC: () => void;
56
+ onEmergencyMode: () => void;
57
+ onRestoreNormal: () => void;
58
+ }
59
+ export interface MemoryAttenuationManagerOptions {
60
+ callbacks: AttenuationCallbacks;
61
+ /** Polling interval in milliseconds. Default: 10000 (10s). */
62
+ checkIntervalMs?: number;
63
+ /** Heap usage fraction to enter YELLOW. Default: 0.70. */
64
+ yellowThreshold?: number;
65
+ /** Heap usage fraction to enter ORANGE. Default: 0.80. */
66
+ orangeThreshold?: number;
67
+ /** Heap usage fraction to enter RED. Default: 0.90. */
68
+ redThreshold?: number;
69
+ /** Heap usage fraction to enter CRITICAL. Default: 0.95. */
70
+ criticalThreshold?: number;
71
+ /** Fraction below threshold before restoring to a lower tier. Default: 0.15. */
72
+ hysteresisPercent?: number;
73
+ /** Normal sensing FPS, restored when dropping below ORANGE. Default: 8. */
74
+ normalFps?: number;
75
+ /** Reduced sensing FPS used at ORANGE and above. Default: 2. */
76
+ reducedFps?: number;
77
+ /**
78
+ * Model shed order from *least important* (index 0, shed first) to
79
+ * *most important* (last index, shed last). During RED, one model is shed
80
+ * per check cycle starting from the end of this array.
81
+ *
82
+ * Default: ['yamnet', 'whisperAsr', 'ferEmotion', 'poseEngagement', 'ageGender', 'gazeTracking']
83
+ */
84
+ shedOrder?: string[];
85
+ }
86
+ export declare class MemoryAttenuationManager extends EventEmitter {
87
+ private readonly callbacks;
88
+ private readonly checkIntervalMs;
89
+ private readonly yellowThreshold;
90
+ private readonly orangeThreshold;
91
+ private readonly redThreshold;
92
+ private readonly criticalThreshold;
93
+ private readonly hysteresisPercent;
94
+ private readonly normalFps;
95
+ private readonly reducedFps;
96
+ private readonly shedOrder;
97
+ private currentTier;
98
+ private intervalHandle;
99
+ private history;
100
+ private actions;
101
+ private cloudInferenceDisabled;
102
+ private federatedLearningDisabled;
103
+ private fpsReduced;
104
+ private shedModels;
105
+ private emergencyModeActive;
106
+ constructor(options: MemoryAttenuationManagerOptions);
107
+ /**
108
+ * Start the periodic memory monitoring interval. The timer is `unref()`'d
109
+ * so it will not keep the Node.js event loop alive on its own.
110
+ */
111
+ start(): void;
112
+ /** Stop the periodic monitoring interval. */
113
+ stop(): void;
114
+ /** Return the current memory tier. */
115
+ getCurrentTier(): MemoryTier;
116
+ /** Take a point-in-time memory snapshot (does NOT trigger actions). */
117
+ getSnapshot(): MemorySnapshot;
118
+ /** Return the last N snapshots (up to 100). */
119
+ getHistory(): MemorySnapshot[];
120
+ /** Return the list of model names currently shed. */
121
+ getShedModels(): string[];
122
+ /** Return the full log of attenuation actions taken. */
123
+ getActions(): AttenuationAction[];
124
+ /**
125
+ * Single check cycle. Exposed as package-internal so tests can drive it
126
+ * deterministically without timers.
127
+ */
128
+ check(): void;
129
+ /**
130
+ * Classify a heap usage percentage into a MemoryTier, applying hysteresis
131
+ * to prevent oscillation at tier boundaries.
132
+ *
133
+ * Escalation uses the raw threshold (jumps to the highest applicable tier).
134
+ * Restoration requires the usage to drop below `threshold - hysteresisPercent`
135
+ * at each boundary, and walks down through all qualifying tiers in a single
136
+ * check. For example with default settings:
137
+ * - Escalate to YELLOW at 70%, restore to GREEN below 55% (70 - 15)
138
+ * - Escalate to ORANGE at 80%, restore to YELLOW below 65% (80 - 15)
139
+ * - Escalate to RED at 90%, restore to ORANGE below 75% (90 - 15)
140
+ * - Escalate to CRITICAL at 95%, restore to RED below 80% (95 - 15)
141
+ */
142
+ private classifyTier;
143
+ /** Apply the actions for entering a given tier (escalating). */
144
+ private applyEscalation;
145
+ /**
146
+ * Apply the restoration actions for entering a given tier (de-escalating).
147
+ * `tier` is the tier we are *entering* on the way down.
148
+ */
149
+ private applyRestoration;
150
+ /**
151
+ * Shed the next model in the shed order. Models are shed from the *end*
152
+ * of `shedOrder` (lowest priority) toward the beginning (highest priority).
153
+ * One model per call.
154
+ */
155
+ private shedNextModel;
156
+ /**
157
+ * Restore all shed models in reverse order (highest priority first,
158
+ * i.e., from the beginning of `shedOrder`).
159
+ */
160
+ private restoreAllShedModels;
161
+ private takeSnapshot;
162
+ private recordAction;
163
+ }
164
+ //# sourceMappingURL=MemoryAttenuationManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryAttenuationManager.d.ts","sourceRoot":"","sources":["../src/MemoryAttenuationManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,400 @@
1
+ "use strict";
2
+ /**
3
+ * MemoryAttenuationManager — Monitors V8 heap and OS memory, applies tiered
4
+ * shedding to keep edge devices stable under pressure.
5
+ *
6
+ * Port of CTV agent's MemoryAttenuationManager.kt, adapted for the V8 heap
7
+ * model. Uses `process.memoryUsage()` for heap metrics and `os.freemem()` /
8
+ * `os.totalmem()` for system-level awareness.
9
+ *
10
+ * Tiers (based on heap usage percentage = heapUsed / heapTotal):
11
+ * GREEN — Normal operation, all systems active
12
+ * YELLOW — >70% heap — disable cloud inference
13
+ * ORANGE — >80% heap — disable federated learning, reduce FPS
14
+ * RED — >90% heap — shed lowest-priority models (one per cycle)
15
+ * CRITICAL — >95% heap — camera-only emergency mode, force GC
16
+ *
17
+ * Hysteresis prevents oscillation: a tier is only restored when usage drops
18
+ * a configurable percentage (default 15%) below the threshold that triggered
19
+ * escalation. For example, YELLOW triggers at 70% but only restores to GREEN
20
+ * when usage falls below 55%.
21
+ */
22
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ var desc = Object.getOwnPropertyDescriptor(m, k);
25
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
26
+ desc = { enumerable: true, get: function() { return m[k]; } };
27
+ }
28
+ Object.defineProperty(o, k2, desc);
29
+ }) : (function(o, m, k, k2) {
30
+ if (k2 === undefined) k2 = k;
31
+ o[k2] = m[k];
32
+ }));
33
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
34
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
35
+ }) : function(o, v) {
36
+ o["default"] = v;
37
+ });
38
+ var __importStar = (this && this.__importStar) || function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.MemoryAttenuationManager = exports.MemoryTier = void 0;
47
+ const events_1 = require("events");
48
+ const os = __importStar(require("os"));
49
+ // ─── Public Types ───────────────────────────────────────────────────────────
50
+ var MemoryTier;
51
+ (function (MemoryTier) {
52
+ MemoryTier["GREEN"] = "GREEN";
53
+ MemoryTier["YELLOW"] = "YELLOW";
54
+ MemoryTier["ORANGE"] = "ORANGE";
55
+ MemoryTier["RED"] = "RED";
56
+ MemoryTier["CRITICAL"] = "CRITICAL";
57
+ })(MemoryTier || (exports.MemoryTier = MemoryTier = {}));
58
+ // ─── Internal Constants ─────────────────────────────────────────────────────
59
+ const MB = 1024 * 1024;
60
+ const MAX_HISTORY = 100;
61
+ const MAX_ACTIONS = 200;
62
+ const DEFAULT_CHECK_INTERVAL_MS = 10000;
63
+ const DEFAULT_YELLOW_THRESHOLD = 0.70;
64
+ const DEFAULT_ORANGE_THRESHOLD = 0.80;
65
+ const DEFAULT_RED_THRESHOLD = 0.90;
66
+ const DEFAULT_CRITICAL_THRESHOLD = 0.95;
67
+ const DEFAULT_HYSTERESIS_PERCENT = 0.15;
68
+ const DEFAULT_NORMAL_FPS = 8;
69
+ const DEFAULT_REDUCED_FPS = 2;
70
+ const DEFAULT_SHED_ORDER = [
71
+ 'yamnet',
72
+ 'whisperAsr',
73
+ 'ferEmotion',
74
+ 'poseEngagement',
75
+ 'ageGender',
76
+ 'gazeTracking',
77
+ ];
78
+ /**
79
+ * Ordered tier list from lowest severity to highest. Used for comparison
80
+ * and iteration when escalating or restoring.
81
+ */
82
+ const TIER_SEVERITY = [
83
+ MemoryTier.GREEN,
84
+ MemoryTier.YELLOW,
85
+ MemoryTier.ORANGE,
86
+ MemoryTier.RED,
87
+ MemoryTier.CRITICAL,
88
+ ];
89
+ function tierIndex(tier) {
90
+ return TIER_SEVERITY.indexOf(tier);
91
+ }
92
+ // ─── Implementation ─────────────────────────────────────────────────────────
93
+ class MemoryAttenuationManager extends events_1.EventEmitter {
94
+ constructor(options) {
95
+ super();
96
+ // Runtime state
97
+ this.currentTier = MemoryTier.GREEN;
98
+ this.intervalHandle = null;
99
+ this.history = [];
100
+ this.actions = [];
101
+ // Tracked attenuation state — what we have already told callers to do
102
+ this.cloudInferenceDisabled = false;
103
+ this.federatedLearningDisabled = false;
104
+ this.fpsReduced = false;
105
+ this.shedModels = new Set();
106
+ this.emergencyModeActive = false;
107
+ this.callbacks = options.callbacks;
108
+ this.checkIntervalMs = options.checkIntervalMs ?? DEFAULT_CHECK_INTERVAL_MS;
109
+ this.yellowThreshold = options.yellowThreshold ?? DEFAULT_YELLOW_THRESHOLD;
110
+ this.orangeThreshold = options.orangeThreshold ?? DEFAULT_ORANGE_THRESHOLD;
111
+ this.redThreshold = options.redThreshold ?? DEFAULT_RED_THRESHOLD;
112
+ this.criticalThreshold = options.criticalThreshold ?? DEFAULT_CRITICAL_THRESHOLD;
113
+ this.hysteresisPercent = options.hysteresisPercent ?? DEFAULT_HYSTERESIS_PERCENT;
114
+ this.normalFps = options.normalFps ?? DEFAULT_NORMAL_FPS;
115
+ this.reducedFps = options.reducedFps ?? DEFAULT_REDUCED_FPS;
116
+ this.shedOrder = options.shedOrder ? [...options.shedOrder] : [...DEFAULT_SHED_ORDER];
117
+ }
118
+ // ─── Public API ─────────────────────────────────────────────────────────
119
+ /**
120
+ * Start the periodic memory monitoring interval. The timer is `unref()`'d
121
+ * so it will not keep the Node.js event loop alive on its own.
122
+ */
123
+ start() {
124
+ if (this.intervalHandle !== null)
125
+ return;
126
+ this.intervalHandle = setInterval(() => this.check(), this.checkIntervalMs);
127
+ this.intervalHandle.unref();
128
+ }
129
+ /** Stop the periodic monitoring interval. */
130
+ stop() {
131
+ if (this.intervalHandle !== null) {
132
+ clearInterval(this.intervalHandle);
133
+ this.intervalHandle = null;
134
+ }
135
+ }
136
+ /** Return the current memory tier. */
137
+ getCurrentTier() {
138
+ return this.currentTier;
139
+ }
140
+ /** Take a point-in-time memory snapshot (does NOT trigger actions). */
141
+ getSnapshot() {
142
+ return this.takeSnapshot();
143
+ }
144
+ /** Return the last N snapshots (up to 100). */
145
+ getHistory() {
146
+ return [...this.history];
147
+ }
148
+ /** Return the list of model names currently shed. */
149
+ getShedModels() {
150
+ return [...this.shedModels];
151
+ }
152
+ /** Return the full log of attenuation actions taken. */
153
+ getActions() {
154
+ return [...this.actions];
155
+ }
156
+ // ─── Core Check Loop ───────────────────────────────────────────────────
157
+ /**
158
+ * Single check cycle. Exposed as package-internal so tests can drive it
159
+ * deterministically without timers.
160
+ */
161
+ check() {
162
+ const snapshot = this.takeSnapshot();
163
+ // Record history (ring buffer, capped at MAX_HISTORY)
164
+ this.history.push(snapshot);
165
+ if (this.history.length > MAX_HISTORY) {
166
+ this.history.shift();
167
+ }
168
+ const newTier = this.classifyTier(snapshot.heapUsedPercent);
169
+ if (newTier !== this.currentTier) {
170
+ const previousTier = this.currentTier;
171
+ this.currentTier = newTier;
172
+ snapshot.tier = newTier;
173
+ // Apply actions for every step between old and new tier
174
+ const oldIdx = tierIndex(previousTier);
175
+ const newIdx = tierIndex(newTier);
176
+ if (newIdx > oldIdx) {
177
+ // Escalating — apply each step from old+1 up to new
178
+ for (let i = oldIdx + 1; i <= newIdx; i++) {
179
+ this.applyEscalation(TIER_SEVERITY[i]);
180
+ }
181
+ }
182
+ else {
183
+ // Restoring — apply each step from old-1 down to new
184
+ for (let i = oldIdx - 1; i >= newIdx; i--) {
185
+ this.applyRestoration(TIER_SEVERITY[i]);
186
+ }
187
+ }
188
+ this.emit('tierChanged', {
189
+ from: previousTier,
190
+ to: newTier,
191
+ snapshot,
192
+ });
193
+ }
194
+ else if (newTier === MemoryTier.RED) {
195
+ // While staying in RED, shed one more model per cycle if available
196
+ this.shedNextModel();
197
+ }
198
+ }
199
+ // ─── Tier Classification (with hysteresis) ─────────────────────────────
200
+ /**
201
+ * Classify a heap usage percentage into a MemoryTier, applying hysteresis
202
+ * to prevent oscillation at tier boundaries.
203
+ *
204
+ * Escalation uses the raw threshold (jumps to the highest applicable tier).
205
+ * Restoration requires the usage to drop below `threshold - hysteresisPercent`
206
+ * at each boundary, and walks down through all qualifying tiers in a single
207
+ * check. For example with default settings:
208
+ * - Escalate to YELLOW at 70%, restore to GREEN below 55% (70 - 15)
209
+ * - Escalate to ORANGE at 80%, restore to YELLOW below 65% (80 - 15)
210
+ * - Escalate to RED at 90%, restore to ORANGE below 75% (90 - 15)
211
+ * - Escalate to CRITICAL at 95%, restore to RED below 80% (95 - 15)
212
+ */
213
+ classifyTier(heapUsedPercent) {
214
+ const currentIdx = tierIndex(this.currentTier);
215
+ // Check for escalation (use raw thresholds, jump to highest applicable)
216
+ if (heapUsedPercent >= this.criticalThreshold * 100 && currentIdx < tierIndex(MemoryTier.CRITICAL)) {
217
+ return MemoryTier.CRITICAL;
218
+ }
219
+ if (heapUsedPercent >= this.redThreshold * 100 && currentIdx < tierIndex(MemoryTier.RED)) {
220
+ return MemoryTier.RED;
221
+ }
222
+ if (heapUsedPercent >= this.orangeThreshold * 100 && currentIdx < tierIndex(MemoryTier.ORANGE)) {
223
+ return MemoryTier.ORANGE;
224
+ }
225
+ if (heapUsedPercent >= this.yellowThreshold * 100 && currentIdx < tierIndex(MemoryTier.YELLOW)) {
226
+ return MemoryTier.YELLOW;
227
+ }
228
+ // Check for restoration — walk downward through each tier boundary,
229
+ // applying hysteresis at each step. This allows multi-step drops in a
230
+ // single check when memory falls far enough.
231
+ const hysteresisThresholds = [
232
+ { tier: MemoryTier.CRITICAL, restoreBelow: (this.criticalThreshold - this.hysteresisPercent) * 100 },
233
+ { tier: MemoryTier.RED, restoreBelow: (this.redThreshold - this.hysteresisPercent) * 100 },
234
+ { tier: MemoryTier.ORANGE, restoreBelow: (this.orangeThreshold - this.hysteresisPercent) * 100 },
235
+ { tier: MemoryTier.YELLOW, restoreBelow: (this.yellowThreshold - this.hysteresisPercent) * 100 },
236
+ ];
237
+ let resolvedTier = this.currentTier;
238
+ for (const { tier, restoreBelow } of hysteresisThresholds) {
239
+ if (resolvedTier === tier && heapUsedPercent < restoreBelow) {
240
+ // Drop one level
241
+ const idx = tierIndex(tier);
242
+ resolvedTier = TIER_SEVERITY[idx - 1];
243
+ }
244
+ }
245
+ return resolvedTier;
246
+ }
247
+ // ─── Escalation Actions ────────────────────────────────────────────────
248
+ /** Apply the actions for entering a given tier (escalating). */
249
+ applyEscalation(tier) {
250
+ switch (tier) {
251
+ case MemoryTier.YELLOW:
252
+ if (!this.cloudInferenceDisabled) {
253
+ this.cloudInferenceDisabled = true;
254
+ this.callbacks.onDisableCloudInference();
255
+ this.recordAction(tier, 'disable_cloud_inference');
256
+ }
257
+ break;
258
+ case MemoryTier.ORANGE:
259
+ if (!this.federatedLearningDisabled) {
260
+ this.federatedLearningDisabled = true;
261
+ this.callbacks.onDisableFederatedLearning();
262
+ this.recordAction(tier, 'disable_federated_learning');
263
+ }
264
+ if (!this.fpsReduced) {
265
+ this.fpsReduced = true;
266
+ this.callbacks.onReduceSensingFps(this.reducedFps);
267
+ this.recordAction(tier, `reduce_fps_to_${this.reducedFps}`);
268
+ }
269
+ break;
270
+ case MemoryTier.RED:
271
+ this.shedNextModel();
272
+ break;
273
+ case MemoryTier.CRITICAL:
274
+ if (!this.emergencyModeActive) {
275
+ this.emergencyModeActive = true;
276
+ this.callbacks.onEmergencyMode();
277
+ this.recordAction(tier, 'emergency_mode');
278
+ }
279
+ // Attempt GC if exposed via --expose-gc
280
+ if (typeof global.gc === 'function') {
281
+ global.gc();
282
+ }
283
+ this.callbacks.onForceGC();
284
+ this.recordAction(tier, 'force_gc');
285
+ break;
286
+ case MemoryTier.GREEN:
287
+ // No escalation action for GREEN
288
+ break;
289
+ }
290
+ }
291
+ // ─── Restoration Actions ───────────────────────────────────────────────
292
+ /**
293
+ * Apply the restoration actions for entering a given tier (de-escalating).
294
+ * `tier` is the tier we are *entering* on the way down.
295
+ */
296
+ applyRestoration(tier) {
297
+ switch (tier) {
298
+ case MemoryTier.RED:
299
+ // Leaving CRITICAL → RED: restore emergency mode
300
+ if (this.emergencyModeActive) {
301
+ this.emergencyModeActive = false;
302
+ this.recordAction(tier, 'exit_emergency_mode');
303
+ }
304
+ break;
305
+ case MemoryTier.ORANGE:
306
+ // Leaving RED → ORANGE: restore all shed models in reverse order
307
+ this.restoreAllShedModels();
308
+ break;
309
+ case MemoryTier.YELLOW:
310
+ // Leaving ORANGE → YELLOW: restore FPS and federated learning
311
+ if (this.fpsReduced) {
312
+ this.fpsReduced = false;
313
+ this.callbacks.onRestoreSensingFps(this.normalFps);
314
+ this.recordAction(tier, `restore_fps_to_${this.normalFps}`);
315
+ }
316
+ if (this.federatedLearningDisabled) {
317
+ this.federatedLearningDisabled = false;
318
+ this.callbacks.onEnableFederatedLearning();
319
+ this.recordAction(tier, 'enable_federated_learning');
320
+ }
321
+ break;
322
+ case MemoryTier.GREEN:
323
+ // Leaving YELLOW → GREEN: restore cloud inference
324
+ if (this.cloudInferenceDisabled) {
325
+ this.cloudInferenceDisabled = false;
326
+ this.callbacks.onEnableCloudInference();
327
+ this.recordAction(tier, 'enable_cloud_inference');
328
+ }
329
+ this.callbacks.onRestoreNormal();
330
+ this.recordAction(tier, 'restore_normal');
331
+ break;
332
+ case MemoryTier.CRITICAL:
333
+ // No restoration for entering CRITICAL (only escalation)
334
+ break;
335
+ }
336
+ }
337
+ // ─── Model Shedding ───────────────────────────────────────────────────
338
+ /**
339
+ * Shed the next model in the shed order. Models are shed from the *end*
340
+ * of `shedOrder` (lowest priority) toward the beginning (highest priority).
341
+ * One model per call.
342
+ */
343
+ shedNextModel() {
344
+ // Walk backwards from end of shedOrder, skipping already-shed models
345
+ for (let i = this.shedOrder.length - 1; i >= 0; i--) {
346
+ const model = this.shedOrder[i];
347
+ if (!this.shedModels.has(model)) {
348
+ this.shedModels.add(model);
349
+ this.callbacks.onShedModel(model);
350
+ this.recordAction(MemoryTier.RED, `shed_model_${model}`);
351
+ return;
352
+ }
353
+ }
354
+ // All models already shed — nothing more to do
355
+ }
356
+ /**
357
+ * Restore all shed models in reverse order (highest priority first,
358
+ * i.e., from the beginning of `shedOrder`).
359
+ */
360
+ restoreAllShedModels() {
361
+ // Restore in forward order through shedOrder (most important first)
362
+ for (const model of this.shedOrder) {
363
+ if (this.shedModels.has(model)) {
364
+ this.shedModels.delete(model);
365
+ this.callbacks.onRestoreModel(model);
366
+ this.recordAction(MemoryTier.ORANGE, `restore_model_${model}`);
367
+ }
368
+ }
369
+ }
370
+ // ─── Snapshot / Recording ──────────────────────────────────────────────
371
+ takeSnapshot() {
372
+ const mem = process.memoryUsage();
373
+ const osTotalBytes = os.totalmem();
374
+ const osFreeBytes = os.freemem();
375
+ const osUsedBytes = osTotalBytes - osFreeBytes;
376
+ return {
377
+ heapUsedMb: Math.round((mem.heapUsed / MB) * 100) / 100,
378
+ heapTotalMb: Math.round((mem.heapTotal / MB) * 100) / 100,
379
+ heapUsedPercent: Math.round((mem.heapUsed / mem.heapTotal) * 10000) / 100,
380
+ rssUsedMb: Math.round((mem.rss / MB) * 100) / 100,
381
+ osFreeMemMb: Math.round((osFreeBytes / MB) * 100) / 100,
382
+ osTotalMemMb: Math.round((osTotalBytes / MB) * 100) / 100,
383
+ osUsedPercent: Math.round((osUsedBytes / osTotalBytes) * 10000) / 100,
384
+ tier: this.currentTier,
385
+ timestamp: Date.now(),
386
+ };
387
+ }
388
+ recordAction(tier, action) {
389
+ this.actions.push({
390
+ tier,
391
+ action,
392
+ timestamp: Date.now(),
393
+ });
394
+ if (this.actions.length > MAX_ACTIONS) {
395
+ this.actions.shift();
396
+ }
397
+ }
398
+ }
399
+ exports.MemoryAttenuationManager = MemoryAttenuationManager;
400
+ //# sourceMappingURL=MemoryAttenuationManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryAttenuationManager.js","sourceRoot":"","sources":["../src/MemoryAttenuationManager.ts"],"names":[],"mappings":"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"}