@unrdf/hooks 5.0.1

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 (33) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +86 -0
  3. package/package.json +70 -0
  4. package/src/hooks/builtin-hooks.mjs +296 -0
  5. package/src/hooks/condition-cache.mjs +109 -0
  6. package/src/hooks/condition-evaluator.mjs +722 -0
  7. package/src/hooks/define-hook.mjs +211 -0
  8. package/src/hooks/effect-sandbox-worker.mjs +170 -0
  9. package/src/hooks/effect-sandbox.mjs +517 -0
  10. package/src/hooks/file-resolver.mjs +387 -0
  11. package/src/hooks/hook-chain-compiler.mjs +236 -0
  12. package/src/hooks/hook-executor-batching.mjs +277 -0
  13. package/src/hooks/hook-executor.mjs +465 -0
  14. package/src/hooks/hook-management.mjs +202 -0
  15. package/src/hooks/hook-scheduler.mjs +413 -0
  16. package/src/hooks/knowledge-hook-engine.mjs +358 -0
  17. package/src/hooks/knowledge-hook-manager.mjs +269 -0
  18. package/src/hooks/observability.mjs +531 -0
  19. package/src/hooks/policy-pack.mjs +572 -0
  20. package/src/hooks/quad-pool.mjs +249 -0
  21. package/src/hooks/quality-metrics.mjs +544 -0
  22. package/src/hooks/security/error-sanitizer.mjs +257 -0
  23. package/src/hooks/security/path-validator.mjs +194 -0
  24. package/src/hooks/security/sandbox-restrictions.mjs +331 -0
  25. package/src/hooks/telemetry.mjs +167 -0
  26. package/src/index.mjs +101 -0
  27. package/src/security/sandbox/browser-executor.mjs +220 -0
  28. package/src/security/sandbox/detector.mjs +342 -0
  29. package/src/security/sandbox/isolated-vm-executor.mjs +373 -0
  30. package/src/security/sandbox/vm2-executor.mjs +217 -0
  31. package/src/security/sandbox/worker-executor-runtime.mjs +74 -0
  32. package/src/security/sandbox/worker-executor.mjs +212 -0
  33. package/src/security/sandbox-adapter.mjs +141 -0
@@ -0,0 +1,373 @@
1
+ /**
2
+ * @file Isolated VM Executor
3
+ * @module security/sandbox/isolated-vm-executor
4
+ *
5
+ * @description
6
+ * Primary sandbox executor using isolated-vm for maximum security.
7
+ * Provides V8 isolate-based execution with:
8
+ * - Full memory isolation
9
+ * - CPU timeout controls
10
+ * - WASM support
11
+ * - Async/await support
12
+ * - Merkle verification of code integrity
13
+ * - OpenTelemetry instrumentation
14
+ */
15
+
16
+ import ivm from 'isolated-vm';
17
+ import { trace, _context } from '@opentelemetry/api';
18
+ import { sha256 } from '@noble/hashes/sha256';
19
+ import { bytesToHex } from '@noble/hashes/utils';
20
+
21
+ const tracer = trace.getTracer('isolated-vm-executor');
22
+
23
+ /**
24
+ * Convert bytes to hex string
25
+ * @param {Uint8Array} bytes
26
+ * @returns {string}
27
+ */
28
+ function toHex(bytes) {
29
+ return bytesToHex(bytes);
30
+ }
31
+
32
+ /**
33
+ * Compute SHA-256 hash of code
34
+ * @param {string} code
35
+ * @returns {string} Hex-encoded hash
36
+ */
37
+ function hashCode(code) {
38
+ const bytes = new TextEncoder().encode(code);
39
+ return toHex(sha256(bytes));
40
+ }
41
+
42
+ /**
43
+ * Threat detection patterns
44
+ */
45
+ const THREAT_PATTERNS = [
46
+ // VM escape attempts
47
+ /constructor\s*\.\s*constructor/i,
48
+ /Function\s*\(\s*['"`]/i,
49
+ /eval\s*\(/i,
50
+ /\[\s*['"`]constructor['"`]\s*\]/i,
51
+
52
+ // Process/require access
53
+ /process\s*\.\s*binding/i,
54
+ /require\s*\(/i,
55
+ /import\s*\(/i,
56
+ /module\s*\.\s*exports/i,
57
+
58
+ // Prototype pollution
59
+ /__proto__/i,
60
+ /prototype\s*\[\s*['"`]/i,
61
+
62
+ // File system access
63
+ /fs\s*\.\s*(read|write)/i,
64
+ /child_process/i,
65
+
66
+ // Network access
67
+ /fetch\s*\(/i,
68
+ /XMLHttpRequest/i,
69
+ /WebSocket/i,
70
+ ];
71
+
72
+ /**
73
+ * Detect potential threats in code
74
+ * @param {string} code
75
+ * @returns {Array<Object>} Detected threats
76
+ */
77
+ function detectThreats(code) {
78
+ const threats = [];
79
+
80
+ for (let i = 0; i < THREAT_PATTERNS.length; i++) {
81
+ const pattern = THREAT_PATTERNS[i];
82
+ if (pattern.test(code)) {
83
+ threats.push({
84
+ patternIndex: i,
85
+ pattern: pattern.toString(),
86
+ severity: i < 4 ? 'critical' : i < 10 ? 'high' : 'medium',
87
+ });
88
+ }
89
+ }
90
+
91
+ return threats;
92
+ }
93
+
94
+ /**
95
+ * Isolated VM Executor
96
+ */
97
+ export class IsolatedVmExecutor {
98
+ /**
99
+ * @param {Object} [config] - Executor configuration
100
+ * @param {number} [config.memoryLimit=128] - Memory limit in MB
101
+ * @param {number} [config.timeout=5000] - Execution timeout in ms
102
+ * @param {boolean} [config.enableWasm=true] - Enable WASM support
103
+ * @param {boolean} [config.enableAsync=true] - Enable async/await
104
+ * @param {boolean} [config.enableThreatDetection=true] - Enable threat detection
105
+ * @param {boolean} [config.strictMode=true] - Enable strict mode
106
+ */
107
+ constructor(config = {}) {
108
+ this.config = {
109
+ memoryLimit: config.memoryLimit || 128,
110
+ timeout: config.timeout || 5000,
111
+ enableWasm: config.enableWasm !== false,
112
+ enableAsync: config.enableAsync !== false,
113
+ enableThreatDetection: config.enableThreatDetection !== false,
114
+ strictMode: config.strictMode !== false,
115
+ ...config,
116
+ };
117
+
118
+ /** @type {Map<string, ivm.Isolate>} */
119
+ this.isolates = new Map();
120
+
121
+ /** @type {Map<string, ivm.Context>} */
122
+ this.contexts = new Map();
123
+
124
+ /** @type {Map<string, string>} - Code hashes for Merkle verification */
125
+ this.codeHashes = new Map();
126
+
127
+ this.executionCount = 0;
128
+ this.totalDuration = 0;
129
+ }
130
+
131
+ /**
132
+ * Execute code in isolated VM
133
+ * @param {string|Function} code - Code to execute
134
+ * @param {Object} [context] - Execution context
135
+ * @param {Object} [options] - Execution options
136
+ * @returns {Promise<Object>} Execution result
137
+ */
138
+ async run(code, context = {}, options = {}) {
139
+ return tracer.startActiveSpan('security.isolate.execute', async span => {
140
+ const startTime = Date.now();
141
+ const executionId = `exec_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
142
+
143
+ try {
144
+ span.setAttributes({
145
+ 'security.executor.type': 'isolated-vm',
146
+ 'security.execution.id': executionId,
147
+ 'security.memoryLimit': this.config.memoryLimit,
148
+ 'security.timeout': options.timeout || this.config.timeout,
149
+ });
150
+
151
+ // Convert function to string if needed
152
+ const codeString = typeof code === 'function' ? code.toString() : code;
153
+
154
+ // Threat detection
155
+ if (this.config.enableThreatDetection) {
156
+ const threats = detectThreats(codeString);
157
+ if (threats.length > 0) {
158
+ const criticalThreats = threats.filter(t => t.severity === 'critical');
159
+ if (criticalThreats.length > 0) {
160
+ span.setAttribute('security.threats.detected', threats.length);
161
+ span.setAttribute('security.threats.critical', criticalThreats.length);
162
+ span.setStatus({
163
+ code: 2,
164
+ message: 'Critical security threat detected',
165
+ });
166
+
167
+ throw new Error(
168
+ `Security threat detected: ${criticalThreats[0].pattern}. ` + `Execution blocked.`
169
+ );
170
+ }
171
+ }
172
+ span.setAttribute('security.threats.count', threats.length);
173
+ }
174
+
175
+ // Compute code hash for Merkle verification
176
+ const codeHash = hashCode(codeString);
177
+ this.codeHashes.set(executionId, codeHash);
178
+ span.setAttribute('security.code.hash', codeHash);
179
+
180
+ // Create isolate
181
+ const isolate = new ivm.Isolate({
182
+ memoryLimit: this.config.memoryLimit,
183
+ inspector: false, // Disable debugging for security
184
+ onCatastrophicError: msg => {
185
+ span.recordException(new Error(`Catastrophic error: ${msg}`));
186
+ this.destroyIsolate(executionId);
187
+ },
188
+ });
189
+
190
+ this.isolates.set(executionId, isolate);
191
+
192
+ // Create context
193
+ const ivmContext = await isolate.createContext();
194
+ this.contexts.set(executionId, ivmContext);
195
+
196
+ // Setup safe global environment
197
+ const jail = ivmContext.global;
198
+ await jail.set('global', jail.derefInto());
199
+
200
+ // Add safe console
201
+ const safeConsole = new ivm.Reference({
202
+ log: (...args) => console.log('[Sandbox]', ...args),
203
+ error: (...args) => console.error('[Sandbox]', ...args),
204
+ warn: (...args) => console.warn('[Sandbox]', ...args),
205
+ info: (...args) => console.info('[Sandbox]', ...args),
206
+ });
207
+ await jail.set('console', safeConsole);
208
+
209
+ // Add JSON support
210
+ const jsonRef = new ivm.Reference({
211
+ parse: str => JSON.parse(str),
212
+ stringify: obj => JSON.stringify(obj),
213
+ });
214
+ await jail.set('JSON', jsonRef);
215
+
216
+ // Add Math support
217
+ const mathRef = new ivm.Reference(Math);
218
+ await jail.set('Math', mathRef);
219
+
220
+ // Add Date support (limited)
221
+ const dateRef = new ivm.Reference({
222
+ now: () => Date.now(),
223
+ });
224
+ await jail.set('Date', dateRef);
225
+
226
+ // Inject context data
227
+ if (context && Object.keys(context).length > 0) {
228
+ for (const [key, value] of Object.entries(context)) {
229
+ const valueRef = new ivm.Reference(value);
230
+ await jail.set(key, valueRef);
231
+ }
232
+ }
233
+
234
+ // Wrap code in strict mode if enabled
235
+ const wrappedCode = this.config.strictMode ? `"use strict";\n${codeString}` : codeString;
236
+
237
+ // Compile and execute
238
+ const script = await isolate.compileScript(wrappedCode);
239
+ const timeout = options.timeout || this.config.timeout;
240
+
241
+ const result = await script.run(ivmContext, {
242
+ timeout,
243
+ reference: true,
244
+ promise: this.config.enableAsync,
245
+ });
246
+
247
+ // Copy result back to main isolate
248
+ const output = result ? await result.copy() : undefined;
249
+
250
+ // Cleanup
251
+ await this.destroyIsolate(executionId);
252
+
253
+ const duration = Date.now() - startTime;
254
+ this.executionCount++;
255
+ this.totalDuration += duration;
256
+
257
+ span.setAttributes({
258
+ 'security.execution.duration': duration,
259
+ 'security.execution.success': true,
260
+ });
261
+ span.setStatus({ code: 1 }); // OK
262
+
263
+ return {
264
+ success: true,
265
+ result: output,
266
+ duration,
267
+ executionId,
268
+ codeHash,
269
+ memoryUsed: await this.getMemoryUsage(executionId).catch(() => ({
270
+ used: 0,
271
+ })),
272
+ };
273
+ } catch (error) {
274
+ const duration = Date.now() - startTime;
275
+
276
+ span.recordException(error);
277
+ span.setAttributes({
278
+ 'security.execution.duration': duration,
279
+ 'security.execution.success': false,
280
+ 'security.error.message': error.message,
281
+ });
282
+ span.setStatus({ code: 2, message: error.message });
283
+
284
+ // Cleanup on error
285
+ await this.destroyIsolate(executionId).catch(() => {});
286
+
287
+ // Categorize error
288
+ let errorType = 'unknown';
289
+ if (error.message?.includes('timed out')) {
290
+ errorType = 'timeout';
291
+ } else if (error.message?.includes('memory')) {
292
+ errorType = 'memory_limit';
293
+ } else if (error.message?.includes('Security threat')) {
294
+ errorType = 'security_threat';
295
+ }
296
+
297
+ span.setAttribute('security.error.type', errorType);
298
+
299
+ return {
300
+ success: false,
301
+ error: error.message,
302
+ errorType,
303
+ duration,
304
+ executionId,
305
+ codeHash: this.codeHashes.get(executionId),
306
+ };
307
+ } finally {
308
+ span.end();
309
+ }
310
+ });
311
+ }
312
+
313
+ /**
314
+ * Get memory usage for execution
315
+ * @param {string} executionId
316
+ * @returns {Promise<Object>}
317
+ */
318
+ async getMemoryUsage(executionId) {
319
+ const isolate = this.isolates.get(executionId);
320
+ if (!isolate) {
321
+ return { used: 0, total: 0, limit: 0, percentage: 0 };
322
+ }
323
+
324
+ const heapStats = await isolate.getHeapStatistics();
325
+ return {
326
+ used: heapStats.used_heap_size,
327
+ total: heapStats.total_heap_size,
328
+ limit: heapStats.heap_size_limit,
329
+ percentage: (heapStats.used_heap_size / heapStats.heap_size_limit) * 100,
330
+ };
331
+ }
332
+
333
+ /**
334
+ * Destroy isolate and free resources
335
+ * @param {string} executionId
336
+ */
337
+ async destroyIsolate(executionId) {
338
+ const isolate = this.isolates.get(executionId);
339
+ if (isolate) {
340
+ try {
341
+ isolate.dispose();
342
+ } catch (err) {
343
+ // Ignore disposal errors
344
+ }
345
+ this.isolates.delete(executionId);
346
+ this.contexts.delete(executionId);
347
+ this.codeHashes.delete(executionId);
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Get executor statistics
353
+ * @returns {Object}
354
+ */
355
+ getStats() {
356
+ return {
357
+ type: 'isolated-vm',
358
+ config: this.config,
359
+ executionCount: this.executionCount,
360
+ averageDuration: this.executionCount > 0 ? this.totalDuration / this.executionCount : 0,
361
+ activeIsolates: this.isolates.size,
362
+ };
363
+ }
364
+
365
+ /**
366
+ * Cleanup all isolates
367
+ */
368
+ async cleanup() {
369
+ for (const executionId of this.isolates.keys()) {
370
+ await this.destroyIsolate(executionId);
371
+ }
372
+ }
373
+ }
@@ -0,0 +1,217 @@
1
+ /**
2
+ * @file VM2 Executor (Legacy - Deprecated)
3
+ * @module security/sandbox/vm2-executor
4
+ *
5
+ * @description
6
+ * Legacy sandbox executor using vm2 (DEPRECATED).
7
+ *
8
+ * ⚠️ SECURITY WARNING ⚠️
9
+ * This executor is DEPRECATED and has known security vulnerabilities.
10
+ * It should only be used for backward compatibility with existing code.
11
+ * Migrate to isolated-vm or worker executors as soon as possible.
12
+ *
13
+ * Known issues:
14
+ * - VM escape vulnerabilities
15
+ * - Prototype pollution risks
16
+ * - No memory isolation
17
+ * - No CPU isolation
18
+ *
19
+ * @deprecated Use IsolatedVmExecutor or WorkerExecutor instead
20
+ */
21
+
22
+ import { trace } from '@opentelemetry/api';
23
+
24
+ const tracer = trace.getTracer('vm2-executor');
25
+
26
+ // Show deprecation warning on first import
27
+ console.warn(
28
+ '\n' +
29
+ '⚠️ ========================================= ⚠️\n' +
30
+ '⚠️ VM2 EXECUTOR DEPRECATION WARNING ⚠️\n' +
31
+ '⚠️ ========================================= ⚠️\n' +
32
+ '\n' +
33
+ 'The vm2 package is deprecated and contains critical security vulnerabilities.\n' +
34
+ 'This executor should NOT be used in production environments.\n' +
35
+ '\n' +
36
+ 'Migrate to:\n' +
37
+ ' - IsolatedVmExecutor (recommended): Full V8 isolation\n' +
38
+ ' - WorkerExecutor: Process-level isolation\n' +
39
+ '\n' +
40
+ 'For more information:\n' +
41
+ ' https://github.com/patriksimek/vm2/issues/533\n' +
42
+ '\n' +
43
+ 'To suppress this warning, set UNRDF_SUPPRESS_VM2_WARNING=1\n' +
44
+ '⚠️ ========================================= ⚠️\n'
45
+ );
46
+
47
+ /**
48
+ * VM2 Executor (Deprecated)
49
+ * @deprecated
50
+ */
51
+ export class Vm2Executor {
52
+ /**
53
+ * @param {Object} [config] - Executor configuration
54
+ * @param {number} [config.timeout=5000] - Execution timeout in ms
55
+ * @param {Array<string>} [config.allowedModules] - Allowed modules
56
+ * @param {boolean} [config.strictMode=true] - Enable strict mode
57
+ */
58
+ constructor(config = {}) {
59
+ this.config = {
60
+ timeout: config.timeout || 5000,
61
+ allowedModules: config.allowedModules || [],
62
+ strictMode: config.strictMode !== false,
63
+ ...config,
64
+ };
65
+
66
+ this.executionCount = 0;
67
+ this.totalDuration = 0;
68
+
69
+ // Show warning on each instantiation unless suppressed
70
+ if (!process.env.UNRDF_SUPPRESS_VM2_WARNING) {
71
+ console.warn(
72
+ '[DEPRECATION] Creating vm2 executor instance - consider migrating to isolated-vm'
73
+ );
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Execute code in vm2
79
+ * @param {string|Function} code - Code to execute
80
+ * @param {Object} [context] - Execution context
81
+ * @param {Object} [options] - Execution options
82
+ * @returns {Promise<Object>} Execution result
83
+ */
84
+ async run(code, context = {}, options = {}) {
85
+ return tracer.startActiveSpan('security.vm2.execute', async span => {
86
+ const startTime = Date.now();
87
+
88
+ try {
89
+ span.setAttributes({
90
+ 'security.executor.type': 'vm2',
91
+ 'security.executor.deprecated': true,
92
+ 'security.executor.security_level': 'low',
93
+ 'security.timeout': options.timeout || this.config.timeout,
94
+ });
95
+
96
+ // Dynamic import of vm2
97
+ let VM;
98
+ try {
99
+ const vm2Module = await import('vm2');
100
+ VM = vm2Module.VM;
101
+ } catch (err) {
102
+ throw new Error('vm2 not available - install with: pnpm add vm2');
103
+ }
104
+
105
+ // Convert function to string if needed
106
+ const codeString = typeof code === 'function' ? code.toString() : code;
107
+
108
+ // Create VM instance
109
+ const vm = new VM({
110
+ timeout: options.timeout || this.config.timeout,
111
+ sandbox: {
112
+ ...this._createSandboxGlobals(context),
113
+ console: this._createSafeConsole(),
114
+ },
115
+ eval: false,
116
+ wasm: false,
117
+ });
118
+
119
+ // Wrap code in strict mode if enabled
120
+ const wrappedCode = this.config.strictMode
121
+ ? `"use strict";\n(function() { ${codeString} })()`
122
+ : `(function() { ${codeString} })()`;
123
+
124
+ // Execute
125
+ const result = vm.run(wrappedCode);
126
+
127
+ const duration = Date.now() - startTime;
128
+ this.executionCount++;
129
+ this.totalDuration += duration;
130
+
131
+ span.setAttributes({
132
+ 'security.execution.duration': duration,
133
+ 'security.execution.success': true,
134
+ });
135
+ span.setStatus({ code: 1 }); // OK
136
+
137
+ return {
138
+ success: true,
139
+ result,
140
+ duration,
141
+ executorType: 'vm2',
142
+ deprecated: true,
143
+ };
144
+ } catch (error) {
145
+ const duration = Date.now() - startTime;
146
+
147
+ span.recordException(error);
148
+ span.setAttributes({
149
+ 'security.execution.duration': duration,
150
+ 'security.execution.success': false,
151
+ 'security.error.message': error.message,
152
+ });
153
+ span.setStatus({ code: 2, message: error.message });
154
+
155
+ return {
156
+ success: false,
157
+ error: error.message,
158
+ duration,
159
+ executorType: 'vm2',
160
+ deprecated: true,
161
+ };
162
+ } finally {
163
+ span.end();
164
+ }
165
+ });
166
+ }
167
+
168
+ /**
169
+ * Create sandbox globals
170
+ * @param {Object} context
171
+ * @returns {Object}
172
+ * @private
173
+ */
174
+ _createSandboxGlobals(context) {
175
+ return {
176
+ Date: { now: () => Date.now() },
177
+ Math,
178
+ JSON,
179
+ ...context,
180
+ };
181
+ }
182
+
183
+ /**
184
+ * Create safe console
185
+ * @returns {Object}
186
+ * @private
187
+ */
188
+ _createSafeConsole() {
189
+ return {
190
+ log: (...args) => console.log('[VM2]', ...args),
191
+ error: (...args) => console.error('[VM2]', ...args),
192
+ warn: (...args) => console.warn('[VM2]', ...args),
193
+ info: (...args) => console.info('[VM2]', ...args),
194
+ };
195
+ }
196
+
197
+ /**
198
+ * Get executor statistics
199
+ * @returns {Object}
200
+ */
201
+ getStats() {
202
+ return {
203
+ type: 'vm2',
204
+ deprecated: true,
205
+ config: this.config,
206
+ executionCount: this.executionCount,
207
+ averageDuration: this.executionCount > 0 ? this.totalDuration / this.executionCount : 0,
208
+ };
209
+ }
210
+
211
+ /**
212
+ * Cleanup (no-op for vm2)
213
+ */
214
+ async cleanup() {
215
+ // vm2 doesn't require cleanup
216
+ }
217
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @file Worker Thread Runtime
3
+ * @description Runtime environment for worker thread execution
4
+ */
5
+
6
+ import { parentPort, workerData } from 'worker_threads';
7
+
8
+ try {
9
+ const { code, context, config } = workerData;
10
+
11
+ // Create safe global environment
12
+ const sandbox = {
13
+ // Allowed globals
14
+ console: {
15
+ log: (...args) => console.log('[Worker]', ...args),
16
+ error: (...args) => console.error('[Worker]', ...args),
17
+ warn: (...args) => console.warn('[Worker]', ...args),
18
+ info: (...args) => console.info('[Worker]', ...args),
19
+ },
20
+ Date: {
21
+ now: () => Date.now(),
22
+ },
23
+ Math,
24
+ JSON,
25
+ // Context data
26
+ ...context,
27
+ };
28
+
29
+ // Add allowed globals from config
30
+ if (config.allowedGlobals) {
31
+ for (const globalName of config.allowedGlobals) {
32
+ if (globalName in globalThis && !(globalName in sandbox)) {
33
+ sandbox[globalName] = globalThis[globalName];
34
+ }
35
+ }
36
+ }
37
+
38
+ // Execute code
39
+ // If code doesn't contain return, wrap it in return for expression evaluation
40
+ const wrappedCode =
41
+ code.trim().includes('return') || code.trim().includes(';') || code.trim().includes('{')
42
+ ? code
43
+ : `return (${code})`;
44
+
45
+ const func = new Function(
46
+ ...Object.keys(sandbox),
47
+ `
48
+ ${config.strictMode ? '"use strict";' : ''}
49
+ ${wrappedCode}
50
+ `
51
+ );
52
+
53
+ const result = func(...Object.values(sandbox));
54
+
55
+ // Get memory usage
56
+ const memoryUsage = process.memoryUsage();
57
+
58
+ // Send result back
59
+ parentPort.postMessage({
60
+ success: true,
61
+ result,
62
+ memoryUsed: {
63
+ used: memoryUsage.heapUsed,
64
+ total: memoryUsage.heapTotal,
65
+ rss: memoryUsage.rss,
66
+ },
67
+ });
68
+ } catch (error) {
69
+ parentPort.postMessage({
70
+ success: false,
71
+ error: error.message,
72
+ stack: error.stack,
73
+ });
74
+ }