@trillboards/edge-core 0.2.1 → 0.2.3
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/dist/JsonFileStore.d.ts +33 -0
- package/dist/JsonFileStore.d.ts.map +1 -0
- package/dist/JsonFileStore.js +210 -0
- package/dist/JsonFileStore.js.map +1 -0
- package/dist/MemoryAttenuationManager.d.ts +164 -0
- package/dist/MemoryAttenuationManager.d.ts.map +1 -0
- package/dist/MemoryAttenuationManager.js +400 -0
- package/dist/MemoryAttenuationManager.js.map +1 -0
- package/dist/ModelManager.d.ts +166 -0
- package/dist/ModelManager.d.ts.map +1 -0
- package/dist/ModelManager.js +580 -0
- package/dist/ModelManager.js.map +1 -0
- package/dist/SignalBuffer.d.ts +20 -12
- package/dist/SignalBuffer.d.ts.map +1 -1
- package/dist/SignalBuffer.js +56 -71
- package/dist/SignalBuffer.js.map +1 -1
- package/dist/SignalStore.d.ts +35 -0
- package/dist/SignalStore.d.ts.map +1 -0
- package/dist/SignalStore.js +13 -0
- package/dist/SignalStore.js.map +1 -0
- package/dist/SqliteStore.d.ts +41 -0
- package/dist/SqliteStore.d.ts.map +1 -0
- package/dist/SqliteStore.js +162 -0
- package/dist/SqliteStore.js.map +1 -0
- package/dist/StatusServer.d.ts +99 -0
- package/dist/StatusServer.d.ts.map +1 -0
- package/dist/StatusServer.js +262 -0
- package/dist/StatusServer.js.map +1 -0
- package/dist/ZKAudienceProver.d.ts +137 -0
- package/dist/ZKAudienceProver.d.ts.map +1 -0
- package/dist/ZKAudienceProver.js +321 -0
- package/dist/ZKAudienceProver.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +40 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JsonFileStore — Zero-dependency signal store using Node.js fs.
|
|
3
|
+
*
|
|
4
|
+
* Storage: configurable path (default: ~/.trillboards/signal_buffer.json)
|
|
5
|
+
* Persistence: debounced writes (every 5s max) + sync write on close()
|
|
6
|
+
* Crash safety: write to .tmp then fs.renameSync (atomic on all platforms)
|
|
7
|
+
* Priority: FACE_BACKED > PERSON_BACKED > SPEECH_ONLY > PROXY_ONLY > EMPTY
|
|
8
|
+
*/
|
|
9
|
+
import type { SignalStore, StoredSignal, SignalStoreStats } from './SignalStore';
|
|
10
|
+
export declare class JsonFileStore implements SignalStore {
|
|
11
|
+
private signals;
|
|
12
|
+
private nextId;
|
|
13
|
+
private readonly filePath;
|
|
14
|
+
private dirty;
|
|
15
|
+
private flushTimer;
|
|
16
|
+
private static readonly FLUSH_INTERVAL_MS;
|
|
17
|
+
constructor(filePath?: string);
|
|
18
|
+
private loadFromDisk;
|
|
19
|
+
private schedulePersist;
|
|
20
|
+
private persistSync;
|
|
21
|
+
private extractEvidenceGrade;
|
|
22
|
+
insert(payload: string, timestamp: number): void;
|
|
23
|
+
getOldest(limit: number): StoredSignal[];
|
|
24
|
+
deleteById(id: number): void;
|
|
25
|
+
deleteOlderThan(cutoffMs: number): number;
|
|
26
|
+
deleteOldestN(n: number): void;
|
|
27
|
+
deleteExceedingRetries(maxRetries: number): void;
|
|
28
|
+
incrementRetry(id: number): void;
|
|
29
|
+
count(): number;
|
|
30
|
+
stats(): SignalStoreStats;
|
|
31
|
+
close(): void;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=JsonFileStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JsonFileStore.d.ts","sourceRoot":"","sources":["../src/JsonFileStore.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAejF,qBAAa,aAAc,YAAW,WAAW;IAC/C,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAQ;gBAErC,QAAQ,CAAC,EAAE,MAAM;IAiB7B,OAAO,CAAC,YAAY;IA0BpB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,oBAAoB;IAW5B,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAYhD,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,EAAE;IAWxC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAQ5B,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAQzC,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ9B,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAMhD,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAQhC,KAAK,IAAI,MAAM;IAIf,KAAK,IAAI,gBAAgB;IAmBzB,KAAK,IAAI,IAAI;CASd"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* JsonFileStore — Zero-dependency signal store using Node.js fs.
|
|
4
|
+
*
|
|
5
|
+
* Storage: configurable path (default: ~/.trillboards/signal_buffer.json)
|
|
6
|
+
* Persistence: debounced writes (every 5s max) + sync write on close()
|
|
7
|
+
* Crash safety: write to .tmp then fs.renameSync (atomic on all platforms)
|
|
8
|
+
* Priority: FACE_BACKED > PERSON_BACKED > SPEECH_ONLY > PROXY_ONLY > EMPTY
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
27
|
+
if (mod && mod.__esModule) return mod;
|
|
28
|
+
var result = {};
|
|
29
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
30
|
+
__setModuleDefault(result, mod);
|
|
31
|
+
return result;
|
|
32
|
+
};
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.JsonFileStore = void 0;
|
|
35
|
+
const fs = __importStar(require("fs"));
|
|
36
|
+
const path = __importStar(require("path"));
|
|
37
|
+
const EVIDENCE_GRADE_PRIORITY = {
|
|
38
|
+
FACE_BACKED: 1,
|
|
39
|
+
PERSON_BACKED: 2,
|
|
40
|
+
SPEECH_ONLY: 3,
|
|
41
|
+
PROXY_ONLY: 4,
|
|
42
|
+
EMPTY: 5,
|
|
43
|
+
};
|
|
44
|
+
class JsonFileStore {
|
|
45
|
+
constructor(filePath) {
|
|
46
|
+
this.signals = [];
|
|
47
|
+
this.nextId = 1;
|
|
48
|
+
this.dirty = false;
|
|
49
|
+
this.flushTimer = null;
|
|
50
|
+
this.filePath =
|
|
51
|
+
filePath ||
|
|
52
|
+
path.join(process.env.HOME || process.env.USERPROFILE || '/tmp', '.trillboards', 'signal_buffer.json');
|
|
53
|
+
const dir = path.dirname(this.filePath);
|
|
54
|
+
if (!fs.existsSync(dir)) {
|
|
55
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
this.loadFromDisk();
|
|
58
|
+
}
|
|
59
|
+
loadFromDisk() {
|
|
60
|
+
try {
|
|
61
|
+
if (fs.existsSync(this.filePath)) {
|
|
62
|
+
const raw = fs.readFileSync(this.filePath, 'utf-8');
|
|
63
|
+
const data = JSON.parse(raw);
|
|
64
|
+
if (Array.isArray(data.signals)) {
|
|
65
|
+
this.signals = data.signals;
|
|
66
|
+
this.nextId = typeof data.nextId === 'number' ? data.nextId : 1;
|
|
67
|
+
// Ensure nextId is higher than any existing signal id
|
|
68
|
+
for (const s of this.signals) {
|
|
69
|
+
if (s.id >= this.nextId) {
|
|
70
|
+
this.nextId = s.id + 1;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Corrupt file — start fresh, log warning
|
|
78
|
+
console.warn(`[JsonFileStore] Corrupt signal buffer at ${this.filePath}, starting fresh`);
|
|
79
|
+
this.signals = [];
|
|
80
|
+
this.nextId = 1;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
schedulePersist() {
|
|
84
|
+
this.dirty = true;
|
|
85
|
+
if (this.flushTimer)
|
|
86
|
+
return;
|
|
87
|
+
this.flushTimer = setTimeout(() => {
|
|
88
|
+
this.flushTimer = null;
|
|
89
|
+
if (this.dirty) {
|
|
90
|
+
this.persistSync();
|
|
91
|
+
}
|
|
92
|
+
}, JsonFileStore.FLUSH_INTERVAL_MS);
|
|
93
|
+
}
|
|
94
|
+
persistSync() {
|
|
95
|
+
this.dirty = false;
|
|
96
|
+
const data = {
|
|
97
|
+
nextId: this.nextId,
|
|
98
|
+
signals: this.signals,
|
|
99
|
+
};
|
|
100
|
+
const json = JSON.stringify(data);
|
|
101
|
+
const tmpPath = this.filePath + '.tmp';
|
|
102
|
+
try {
|
|
103
|
+
fs.writeFileSync(tmpPath, json, 'utf-8');
|
|
104
|
+
fs.renameSync(tmpPath, this.filePath);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
console.error(`[JsonFileStore] Failed to persist signal buffer:`, err);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
extractEvidenceGrade(payload) {
|
|
111
|
+
try {
|
|
112
|
+
const parsed = JSON.parse(payload);
|
|
113
|
+
return typeof parsed.evidenceGrade === 'string'
|
|
114
|
+
? parsed.evidenceGrade
|
|
115
|
+
: 'EMPTY';
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return 'EMPTY';
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
insert(payload, timestamp) {
|
|
122
|
+
const signal = {
|
|
123
|
+
id: this.nextId++,
|
|
124
|
+
payload,
|
|
125
|
+
timestamp,
|
|
126
|
+
retryCount: 0,
|
|
127
|
+
evidenceGrade: this.extractEvidenceGrade(payload),
|
|
128
|
+
};
|
|
129
|
+
this.signals.push(signal);
|
|
130
|
+
this.schedulePersist();
|
|
131
|
+
}
|
|
132
|
+
getOldest(limit) {
|
|
133
|
+
// Sort by priority (evidence grade), then by timestamp (oldest first)
|
|
134
|
+
const sorted = [...this.signals].sort((a, b) => {
|
|
135
|
+
const prioA = EVIDENCE_GRADE_PRIORITY[a.evidenceGrade || 'EMPTY'] || 5;
|
|
136
|
+
const prioB = EVIDENCE_GRADE_PRIORITY[b.evidenceGrade || 'EMPTY'] || 5;
|
|
137
|
+
if (prioA !== prioB)
|
|
138
|
+
return prioA - prioB;
|
|
139
|
+
return a.timestamp - b.timestamp;
|
|
140
|
+
});
|
|
141
|
+
return sorted.slice(0, limit);
|
|
142
|
+
}
|
|
143
|
+
deleteById(id) {
|
|
144
|
+
const idx = this.signals.findIndex((s) => s.id === id);
|
|
145
|
+
if (idx !== -1) {
|
|
146
|
+
this.signals.splice(idx, 1);
|
|
147
|
+
this.schedulePersist();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
deleteOlderThan(cutoffMs) {
|
|
151
|
+
const before = this.signals.length;
|
|
152
|
+
this.signals = this.signals.filter((s) => s.timestamp >= cutoffMs);
|
|
153
|
+
const deleted = before - this.signals.length;
|
|
154
|
+
if (deleted > 0)
|
|
155
|
+
this.schedulePersist();
|
|
156
|
+
return deleted;
|
|
157
|
+
}
|
|
158
|
+
deleteOldestN(n) {
|
|
159
|
+
if (n <= 0 || this.signals.length === 0)
|
|
160
|
+
return;
|
|
161
|
+
// Sort by timestamp ascending, remove the oldest N
|
|
162
|
+
this.signals.sort((a, b) => a.timestamp - b.timestamp);
|
|
163
|
+
this.signals.splice(0, n);
|
|
164
|
+
this.schedulePersist();
|
|
165
|
+
}
|
|
166
|
+
deleteExceedingRetries(maxRetries) {
|
|
167
|
+
const before = this.signals.length;
|
|
168
|
+
this.signals = this.signals.filter((s) => s.retryCount < maxRetries);
|
|
169
|
+
if (this.signals.length < before)
|
|
170
|
+
this.schedulePersist();
|
|
171
|
+
}
|
|
172
|
+
incrementRetry(id) {
|
|
173
|
+
const signal = this.signals.find((s) => s.id === id);
|
|
174
|
+
if (signal) {
|
|
175
|
+
signal.retryCount++;
|
|
176
|
+
this.schedulePersist();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
count() {
|
|
180
|
+
return this.signals.length;
|
|
181
|
+
}
|
|
182
|
+
stats() {
|
|
183
|
+
const byGrade = {};
|
|
184
|
+
let oldest = null;
|
|
185
|
+
for (const s of this.signals) {
|
|
186
|
+
const grade = s.evidenceGrade || 'EMPTY';
|
|
187
|
+
byGrade[grade] = (byGrade[grade] || 0) + 1;
|
|
188
|
+
if (oldest === null || s.timestamp < oldest) {
|
|
189
|
+
oldest = s.timestamp;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
total: this.signals.length,
|
|
194
|
+
byEvidenceGrade: byGrade,
|
|
195
|
+
oldestTimestampMs: oldest,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
close() {
|
|
199
|
+
if (this.flushTimer) {
|
|
200
|
+
clearTimeout(this.flushTimer);
|
|
201
|
+
this.flushTimer = null;
|
|
202
|
+
}
|
|
203
|
+
if (this.dirty) {
|
|
204
|
+
this.persistSync();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
exports.JsonFileStore = JsonFileStore;
|
|
209
|
+
JsonFileStore.FLUSH_INTERVAL_MS = 5000;
|
|
210
|
+
//# sourceMappingURL=JsonFileStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JsonFileStore.js","sourceRoot":"","sources":["../src/JsonFileStore.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,uCAAyB;AACzB,2CAA6B;AAG7B,MAAM,uBAAuB,GAA2B;IACtD,WAAW,EAAE,CAAC;IACd,aAAa,EAAE,CAAC;IAChB,WAAW,EAAE,CAAC;IACd,UAAU,EAAE,CAAC;IACb,KAAK,EAAE,CAAC;CACT,CAAC;AAOF,MAAa,aAAa;IAQxB,YAAY,QAAiB;QAPrB,YAAO,GAAmB,EAAE,CAAC;QAC7B,WAAM,GAAW,CAAC,CAAC;QAEnB,UAAK,GAAG,KAAK,CAAC;QACd,eAAU,GAAyC,IAAI,CAAC;QAI9D,IAAI,CAAC,QAAQ;YACX,QAAQ;gBACR,IAAI,CAAC,IAAI,CACP,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,MAAM,EACrD,cAAc,EACd,oBAAoB,CACrB,CAAC;QAEJ,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAEO,YAAY;QAClB,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACpD,MAAM,IAAI,GAAkB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC5C,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBAChC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;oBAC5B,IAAI,CAAC,MAAM,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;oBAChE,sDAAsD;oBACtD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;wBAC7B,IAAI,CAAC,CAAC,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;4BACxB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;wBACzB,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,0CAA0C;YAC1C,OAAO,CAAC,IAAI,CACV,4CAA4C,IAAI,CAAC,QAAQ,kBAAkB,CAC5E,CAAC;YACF,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;YAClB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAEO,eAAe;QACrB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO;QAC5B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE;YAChC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,CAAC;QACH,CAAC,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IACtC,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,MAAM,IAAI,GAAkB;YAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC;QACvC,IAAI,CAAC;YACH,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;YACzC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,kDAAkD,EAAE,GAAG,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAEO,oBAAoB,CAAC,OAAe;QAC1C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACnC,OAAO,OAAO,MAAM,CAAC,aAAa,KAAK,QAAQ;gBAC7C,CAAC,CAAC,MAAM,CAAC,aAAa;gBACtB,CAAC,CAAC,OAAO,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IAED,MAAM,CAAC,OAAe,EAAE,SAAiB;QACvC,MAAM,MAAM,GAAiB;YAC3B,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE;YACjB,OAAO;YACP,SAAS;YACT,UAAU,EAAE,CAAC;YACb,aAAa,EAAE,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC;SAClD,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAED,SAAS,CAAC,KAAa;QACrB,sEAAsE;QACtE,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC7C,MAAM,KAAK,GAAG,uBAAuB,CAAC,CAAC,CAAC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;YACvE,MAAM,KAAK,GAAG,uBAAuB,CAAC,CAAC,CAAC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;YACvE,IAAI,KAAK,KAAK,KAAK;gBAAE,OAAO,KAAK,GAAG,KAAK,CAAC;YAC1C,OAAO,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;QACnC,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;IAED,UAAU,CAAC,EAAU;QACnB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACvD,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC5B,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAED,eAAe,CAAC,QAAgB;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QACnC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC,CAAC;QACnE,MAAM,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QAC7C,IAAI,OAAO,GAAG,CAAC;YAAE,IAAI,CAAC,eAAe,EAAE,CAAC;QACxC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,aAAa,CAAC,CAAS;QACrB,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAChD,mDAAmD;QACnD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAED,sBAAsB,CAAC,UAAkB;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QACnC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,UAAU,CAAC,CAAC;QACrE,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM;YAAE,IAAI,CAAC,eAAe,EAAE,CAAC;IAC3D,CAAC;IAED,cAAc,CAAC,EAAU;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACrD,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7B,CAAC;IAED,KAAK;QACH,MAAM,OAAO,GAA2B,EAAE,CAAC;QAC3C,IAAI,MAAM,GAAkB,IAAI,CAAC;QAEjC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,CAAC,CAAC,aAAa,IAAI,OAAO,CAAC;YACzC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAC3C,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,SAAS,GAAG,MAAM,EAAE,CAAC;gBAC5C,MAAM,GAAG,CAAC,CAAC,SAAS,CAAC;YACvB,CAAC;QACH,CAAC;QAED,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC1B,eAAe,EAAE,OAAO;YACxB,iBAAiB,EAAE,MAAM;SAC1B,CAAC;IACJ,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;;AArLH,sCAsLC;AAhLyB,+BAAiB,GAAG,IAAI,AAAP,CAAQ"}
|
|
@@ -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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"}
|