@elizaos/plugin-vision 2.0.0-alpha.4 → 2.0.0-alpha.5
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/index.js +68 -16
- package/dist/index.js.map +4 -4
- package/package.json +8 -6
- package/dist/workers/florence2-worker.js +0 -121102
- package/dist/workers/florence2-worker.js.map +0 -92
- package/dist/workers/ocr-worker.js +0 -128510
- package/dist/workers/ocr-worker.js.map +0 -137
- package/dist/workers/screen-capture-worker.js +0 -359
- package/dist/workers/screen-capture-worker.js.map +0 -11
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __toESM = (mod, isNodeMode, target) => {
|
|
7
|
-
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
8
|
-
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
9
|
-
for (let key of __getOwnPropNames(mod))
|
|
10
|
-
if (!__hasOwnProp.call(to, key))
|
|
11
|
-
__defProp(to, key, {
|
|
12
|
-
get: () => mod[key],
|
|
13
|
-
enumerable: true
|
|
14
|
-
});
|
|
15
|
-
return to;
|
|
16
|
-
};
|
|
17
|
-
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
18
|
-
var __export = (target, all) => {
|
|
19
|
-
for (var name in all)
|
|
20
|
-
__defProp(target, name, {
|
|
21
|
-
get: all[name],
|
|
22
|
-
enumerable: true,
|
|
23
|
-
configurable: true,
|
|
24
|
-
set: (newValue) => all[name] = () => newValue
|
|
25
|
-
});
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// src/workers/screen-capture-worker.ts
|
|
29
|
-
var import_node_child_process = require("node:child_process");
|
|
30
|
-
var fs = __toESM(require("node:fs/promises"));
|
|
31
|
-
var path = __toESM(require("node:path"));
|
|
32
|
-
var import_node_util = require("node:util");
|
|
33
|
-
var import_node_worker_threads2 = require("node:worker_threads");
|
|
34
|
-
var import_sharp = __toESM(require("sharp"));
|
|
35
|
-
|
|
36
|
-
// src/workers/worker-logger.ts
|
|
37
|
-
var import_node_worker_threads = require("node:worker_threads");
|
|
38
|
-
var logger = {
|
|
39
|
-
info: (message, ...args) => {
|
|
40
|
-
const logMessage = {
|
|
41
|
-
type: "log",
|
|
42
|
-
level: "info",
|
|
43
|
-
message,
|
|
44
|
-
args,
|
|
45
|
-
timestamp: new Date().toISOString()
|
|
46
|
-
};
|
|
47
|
-
if (import_node_worker_threads.parentPort) {
|
|
48
|
-
import_node_worker_threads.parentPort.postMessage(logMessage);
|
|
49
|
-
} else {
|
|
50
|
-
console.log(`[INFO] ${message}`, ...args);
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
warn: (message, ...args) => {
|
|
54
|
-
const logMessage = {
|
|
55
|
-
type: "log",
|
|
56
|
-
level: "warn",
|
|
57
|
-
message,
|
|
58
|
-
args,
|
|
59
|
-
timestamp: new Date().toISOString()
|
|
60
|
-
};
|
|
61
|
-
if (import_node_worker_threads.parentPort) {
|
|
62
|
-
import_node_worker_threads.parentPort.postMessage(logMessage);
|
|
63
|
-
} else {
|
|
64
|
-
console.warn(`[WARN] ${message}`, ...args);
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
error: (message, ...args) => {
|
|
68
|
-
const logMessage = {
|
|
69
|
-
type: "log",
|
|
70
|
-
level: "error",
|
|
71
|
-
message,
|
|
72
|
-
args,
|
|
73
|
-
timestamp: new Date().toISOString()
|
|
74
|
-
};
|
|
75
|
-
if (import_node_worker_threads.parentPort) {
|
|
76
|
-
import_node_worker_threads.parentPort.postMessage(logMessage);
|
|
77
|
-
} else {
|
|
78
|
-
console.error(`[ERROR] ${message}`, ...args);
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
debug: (message, ...args) => {
|
|
82
|
-
const logMessage = {
|
|
83
|
-
type: "log",
|
|
84
|
-
level: "debug",
|
|
85
|
-
message,
|
|
86
|
-
args,
|
|
87
|
-
timestamp: new Date().toISOString()
|
|
88
|
-
};
|
|
89
|
-
if (import_node_worker_threads.parentPort) {
|
|
90
|
-
import_node_worker_threads.parentPort.postMessage(logMessage);
|
|
91
|
-
} else {
|
|
92
|
-
console.debug(`[DEBUG] ${message}`, ...args);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
// src/workers/screen-capture-worker.ts
|
|
98
|
-
var execAsync = import_node_util.promisify(import_node_child_process.exec);
|
|
99
|
-
|
|
100
|
-
class ScreenCaptureWorker {
|
|
101
|
-
config;
|
|
102
|
-
sharedBuffer;
|
|
103
|
-
dataView;
|
|
104
|
-
atomicState;
|
|
105
|
-
isRunning = true;
|
|
106
|
-
frameCount = 0;
|
|
107
|
-
lastFPSReport = Date.now();
|
|
108
|
-
displays = [];
|
|
109
|
-
currentDisplayIndex = 0;
|
|
110
|
-
FRAME_ID_INDEX = 0;
|
|
111
|
-
WRITE_LOCK_INDEX = 1;
|
|
112
|
-
WIDTH_INDEX = 2;
|
|
113
|
-
HEIGHT_INDEX = 3;
|
|
114
|
-
DISPLAY_INDEX = 4;
|
|
115
|
-
TIMESTAMP_INDEX = 5;
|
|
116
|
-
DATA_OFFSET = 24;
|
|
117
|
-
constructor(config, sharedBuffer) {
|
|
118
|
-
this.config = config;
|
|
119
|
-
this.sharedBuffer = sharedBuffer;
|
|
120
|
-
this.dataView = new DataView(sharedBuffer);
|
|
121
|
-
this.atomicState = new Int32Array(sharedBuffer, 0, 6);
|
|
122
|
-
}
|
|
123
|
-
async initialize() {
|
|
124
|
-
this.displays = await this.getDisplays();
|
|
125
|
-
if (this.displays.length === 0) {
|
|
126
|
-
throw new Error("No displays found");
|
|
127
|
-
}
|
|
128
|
-
if (this.config.displayIndex !== undefined && this.config.displayIndex < this.displays.length) {
|
|
129
|
-
this.currentDisplayIndex = this.config.displayIndex;
|
|
130
|
-
}
|
|
131
|
-
logger.info(`[ScreenCaptureWorker] Initialized with ${this.displays.length} displays`);
|
|
132
|
-
this.displays.forEach((d, i) => {
|
|
133
|
-
logger.info(` Display ${i}: ${d.name} (${d.width}x${d.height}) ${d.isPrimary ? "[PRIMARY]" : ""}`);
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
async getDisplays() {
|
|
137
|
-
const platform = process.platform;
|
|
138
|
-
try {
|
|
139
|
-
if (platform === "darwin") {
|
|
140
|
-
const { stdout } = await execAsync("system_profiler SPDisplaysDataType -json");
|
|
141
|
-
const data = JSON.parse(stdout);
|
|
142
|
-
const displays = [];
|
|
143
|
-
if (data.SPDisplaysDataType?.[0]) {
|
|
144
|
-
const gpuInfo = data.SPDisplaysDataType[0];
|
|
145
|
-
const items = gpuInfo._items || [];
|
|
146
|
-
items.forEach((item, index) => {
|
|
147
|
-
const resolution = item.native_resolution;
|
|
148
|
-
if (resolution) {
|
|
149
|
-
const match = resolution.match(/(\d+) x (\d+)/);
|
|
150
|
-
if (match) {
|
|
151
|
-
displays.push({
|
|
152
|
-
id: `display-${index}`,
|
|
153
|
-
name: item._name || `Display ${index + 1}`,
|
|
154
|
-
width: parseInt(match[1], 10),
|
|
155
|
-
height: parseInt(match[2], 10),
|
|
156
|
-
x: 0,
|
|
157
|
-
y: 0,
|
|
158
|
-
isPrimary: index === 0
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
return displays;
|
|
165
|
-
} else if (platform === "linux") {
|
|
166
|
-
const { stdout } = await execAsync("xrandr --query");
|
|
167
|
-
const displays = [];
|
|
168
|
-
const lines = stdout.split(`
|
|
169
|
-
`);
|
|
170
|
-
for (const line of lines) {
|
|
171
|
-
if (line.includes(" connected")) {
|
|
172
|
-
const match = line.match(/^(\S+) connected (?:primary )?(\d+)x(\d+)\+(\d+)\+(\d+)/);
|
|
173
|
-
if (match) {
|
|
174
|
-
displays.push({
|
|
175
|
-
id: match[1],
|
|
176
|
-
name: match[1],
|
|
177
|
-
width: parseInt(match[2], 10),
|
|
178
|
-
height: parseInt(match[3], 10),
|
|
179
|
-
x: parseInt(match[4], 10),
|
|
180
|
-
y: parseInt(match[5], 10),
|
|
181
|
-
isPrimary: line.includes("primary")
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
return displays;
|
|
187
|
-
} else if (platform === "win32") {
|
|
188
|
-
const { stdout } = await execAsync("wmic path Win32_DesktopMonitor get DeviceID,ScreenWidth,ScreenHeight /format:csv");
|
|
189
|
-
const displays = [];
|
|
190
|
-
const lines = stdout.trim().split(`
|
|
191
|
-
`).slice(2);
|
|
192
|
-
lines.forEach((line, index) => {
|
|
193
|
-
const parts = line.split(",");
|
|
194
|
-
if (parts.length >= 4) {
|
|
195
|
-
const width = parseInt(parts[2], 10);
|
|
196
|
-
const height = parseInt(parts[3], 10);
|
|
197
|
-
if (!Number.isNaN(width) && !Number.isNaN(height)) {
|
|
198
|
-
displays.push({
|
|
199
|
-
id: parts[1],
|
|
200
|
-
name: parts[1] || `Display ${index + 1}`,
|
|
201
|
-
width,
|
|
202
|
-
height,
|
|
203
|
-
x: 0,
|
|
204
|
-
y: 0,
|
|
205
|
-
isPrimary: index === 0
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
return displays.length > 0 ? displays : [
|
|
211
|
-
{
|
|
212
|
-
id: "primary",
|
|
213
|
-
name: "Primary Display",
|
|
214
|
-
width: 1920,
|
|
215
|
-
height: 1080,
|
|
216
|
-
x: 0,
|
|
217
|
-
y: 0,
|
|
218
|
-
isPrimary: true
|
|
219
|
-
}
|
|
220
|
-
];
|
|
221
|
-
}
|
|
222
|
-
} catch (error) {
|
|
223
|
-
logger.error("[ScreenCaptureWorker] Failed to get display info:", error);
|
|
224
|
-
}
|
|
225
|
-
return [
|
|
226
|
-
{
|
|
227
|
-
id: "default",
|
|
228
|
-
name: "Default Display",
|
|
229
|
-
width: 1920,
|
|
230
|
-
height: 1080,
|
|
231
|
-
x: 0,
|
|
232
|
-
y: 0,
|
|
233
|
-
isPrimary: true
|
|
234
|
-
}
|
|
235
|
-
];
|
|
236
|
-
}
|
|
237
|
-
async run() {
|
|
238
|
-
await this.initialize();
|
|
239
|
-
logger.info("[ScreenCaptureWorker] Starting capture loop...");
|
|
240
|
-
while (this.isRunning) {
|
|
241
|
-
const startTime = Date.now();
|
|
242
|
-
try {
|
|
243
|
-
await this.captureFrame();
|
|
244
|
-
this.frameCount++;
|
|
245
|
-
const now = Date.now();
|
|
246
|
-
if (now - this.lastFPSReport >= 1000) {
|
|
247
|
-
const fps = this.frameCount / ((now - this.lastFPSReport) / 1000);
|
|
248
|
-
logger.info(`[ScreenCaptureWorker] FPS: ${fps.toFixed(2)}, Display: ${this.currentDisplayIndex}`);
|
|
249
|
-
import_node_worker_threads2.parentPort?.postMessage({
|
|
250
|
-
type: "fps",
|
|
251
|
-
fps,
|
|
252
|
-
frameCount: this.frameCount,
|
|
253
|
-
displayIndex: this.currentDisplayIndex
|
|
254
|
-
});
|
|
255
|
-
this.frameCount = 0;
|
|
256
|
-
this.lastFPSReport = now;
|
|
257
|
-
}
|
|
258
|
-
if (this.config.captureAllDisplays && this.displays.length > 1) {
|
|
259
|
-
this.currentDisplayIndex = (this.currentDisplayIndex + 1) % this.displays.length;
|
|
260
|
-
}
|
|
261
|
-
if (this.config.targetFPS) {
|
|
262
|
-
const frameTime = 1000 / this.config.targetFPS;
|
|
263
|
-
const elapsed = Date.now() - startTime;
|
|
264
|
-
if (elapsed < frameTime) {
|
|
265
|
-
await new Promise((resolve) => setTimeout(resolve, frameTime - elapsed));
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
} catch (error) {
|
|
269
|
-
logger.error("[ScreenCaptureWorker] Capture error:", error);
|
|
270
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
async captureFrame() {
|
|
275
|
-
const display = this.displays[this.currentDisplayIndex];
|
|
276
|
-
const tempFile = path.join(process.cwd(), `temp_screen_${Date.now()}_${this.currentDisplayIndex}.png`);
|
|
277
|
-
try {
|
|
278
|
-
await this.captureScreenToFile(tempFile, display);
|
|
279
|
-
const imageBuffer = await fs.readFile(tempFile);
|
|
280
|
-
const image = import_sharp.default(imageBuffer);
|
|
281
|
-
const metadata = await image.metadata();
|
|
282
|
-
const width = metadata.width || display.width;
|
|
283
|
-
const height = metadata.height || display.height;
|
|
284
|
-
const rawData = await image.ensureAlpha().raw().toBuffer();
|
|
285
|
-
while (Atomics.compareExchange(this.atomicState, this.WRITE_LOCK_INDEX, 0, 1) !== 0) {}
|
|
286
|
-
try {
|
|
287
|
-
Atomics.store(this.atomicState, this.WIDTH_INDEX, width);
|
|
288
|
-
Atomics.store(this.atomicState, this.HEIGHT_INDEX, height);
|
|
289
|
-
Atomics.store(this.atomicState, this.DISPLAY_INDEX, this.currentDisplayIndex);
|
|
290
|
-
Atomics.store(this.atomicState, this.TIMESTAMP_INDEX, Date.now());
|
|
291
|
-
const maxDataSize = this.sharedBuffer.byteLength - this.DATA_OFFSET;
|
|
292
|
-
const dataSize = Math.min(rawData.length, maxDataSize);
|
|
293
|
-
for (let i = 0;i < dataSize; i++) {
|
|
294
|
-
this.dataView.setUint8(this.DATA_OFFSET + i, rawData[i]);
|
|
295
|
-
}
|
|
296
|
-
Atomics.add(this.atomicState, this.FRAME_ID_INDEX, 1);
|
|
297
|
-
} finally {
|
|
298
|
-
Atomics.store(this.atomicState, this.WRITE_LOCK_INDEX, 0);
|
|
299
|
-
}
|
|
300
|
-
await fs.unlink(tempFile).catch(() => {});
|
|
301
|
-
} catch (error) {
|
|
302
|
-
await fs.unlink(tempFile).catch(() => {});
|
|
303
|
-
throw error;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
async captureScreenToFile(outputPath, display) {
|
|
307
|
-
const platform = process.platform;
|
|
308
|
-
try {
|
|
309
|
-
if (platform === "darwin") {
|
|
310
|
-
const displayArg = this.currentDisplayIndex > 0 ? `-D ${this.currentDisplayIndex + 1}` : "";
|
|
311
|
-
await execAsync(`screencapture -x ${displayArg} "${outputPath}"`);
|
|
312
|
-
} else if (platform === "linux") {
|
|
313
|
-
if (display.x !== 0 || display.y !== 0) {
|
|
314
|
-
await execAsync(`scrot -a ${display.x},${display.y},${display.width},${display.height} "${outputPath}"`);
|
|
315
|
-
} else {
|
|
316
|
-
await execAsync(`scrot "${outputPath}"`);
|
|
317
|
-
}
|
|
318
|
-
} else if (platform === "win32") {
|
|
319
|
-
const script = `
|
|
320
|
-
Add-Type -AssemblyName System.Windows.Forms;
|
|
321
|
-
Add-Type -AssemblyName System.Drawing;
|
|
322
|
-
$screens = [System.Windows.Forms.Screen]::AllScreens;
|
|
323
|
-
$screen = $screens[${this.currentDisplayIndex}];
|
|
324
|
-
$bounds = $screen.Bounds;
|
|
325
|
-
$bitmap = New-Object System.Drawing.Bitmap $bounds.Width, $bounds.Height;
|
|
326
|
-
$graphics = [System.Drawing.Graphics]::FromImage($bitmap);
|
|
327
|
-
$graphics.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size);
|
|
328
|
-
$bitmap.Save('${outputPath.replace(/\\/g, "\\\\")}');
|
|
329
|
-
$graphics.Dispose();
|
|
330
|
-
$bitmap.Dispose();
|
|
331
|
-
`;
|
|
332
|
-
await execAsync(`powershell -Command "${script.replace(/\n/g, " ")}"`);
|
|
333
|
-
}
|
|
334
|
-
} catch (error) {
|
|
335
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
336
|
-
throw new Error(`Screen capture failed: ${errorMessage}`);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
stop() {
|
|
340
|
-
this.isRunning = false;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
if (import_node_worker_threads2.parentPort) {
|
|
344
|
-
const { config, sharedBuffer } = import_node_worker_threads2.workerData;
|
|
345
|
-
const worker = new ScreenCaptureWorker(config, sharedBuffer);
|
|
346
|
-
import_node_worker_threads2.parentPort.on("message", (msg) => {
|
|
347
|
-
if (msg.type === "stop") {
|
|
348
|
-
worker.stop();
|
|
349
|
-
}
|
|
350
|
-
});
|
|
351
|
-
worker.run().catch((error) => {
|
|
352
|
-
logger.error("[ScreenCaptureWorker] Fatal error:", error);
|
|
353
|
-
import_node_worker_threads2.parentPort?.postMessage({ type: "error", error: error.message });
|
|
354
|
-
process.exit(1);
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
//# debugId=91B84423455CE7E564756E2164756E21
|
|
359
|
-
//# sourceMappingURL=screen-capture-worker.js.map
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/workers/screen-capture-worker.ts", "../../src/workers/worker-logger.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import { exec } from \"node:child_process\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { parentPort, workerData } from \"node:worker_threads\";\nimport sharp from \"sharp\";\nimport { logger } from \"./worker-logger\";\n\nconst execAsync = promisify(exec);\n\ninterface WorkerConfig {\n displayIndex?: number;\n captureAllDisplays?: boolean;\n targetFPS?: number;\n sharedBufferSize: number;\n}\n\ninterface DisplayInfo {\n id: string;\n name: string;\n width: number;\n height: number;\n x: number;\n y: number;\n isPrimary?: boolean;\n}\n\nclass ScreenCaptureWorker {\n private config: WorkerConfig;\n private sharedBuffer: SharedArrayBuffer;\n private dataView: DataView;\n private atomicState: Int32Array;\n private isRunning = true;\n private frameCount = 0;\n private lastFPSReport = Date.now();\n private displays: DisplayInfo[] = [];\n private currentDisplayIndex = 0;\n\n // Atomic indices\n private readonly FRAME_ID_INDEX = 0;\n private readonly WRITE_LOCK_INDEX = 1;\n private readonly WIDTH_INDEX = 2;\n private readonly HEIGHT_INDEX = 3;\n private readonly DISPLAY_INDEX = 4;\n private readonly TIMESTAMP_INDEX = 5;\n private readonly DATA_OFFSET = 24; // 6 * 4 bytes for metadata\n\n constructor(config: WorkerConfig, sharedBuffer: SharedArrayBuffer) {\n this.config = config;\n this.sharedBuffer = sharedBuffer;\n this.dataView = new DataView(sharedBuffer);\n this.atomicState = new Int32Array(sharedBuffer, 0, 6);\n }\n\n async initialize(): Promise<void> {\n // Get display information\n this.displays = await this.getDisplays();\n\n if (this.displays.length === 0) {\n throw new Error(\"No displays found\");\n }\n\n // Set initial display\n if (this.config.displayIndex !== undefined && this.config.displayIndex < this.displays.length) {\n this.currentDisplayIndex = this.config.displayIndex;\n }\n\n logger.info(`[ScreenCaptureWorker] Initialized with ${this.displays.length} displays`);\n this.displays.forEach((d, i) => {\n logger.info(\n ` Display ${i}: ${d.name} (${d.width}x${d.height}) ${d.isPrimary ? \"[PRIMARY]\" : \"\"}`\n );\n });\n }\n\n private async getDisplays(): Promise<DisplayInfo[]> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // macOS: Use system_profiler\n const { stdout } = await execAsync(\"system_profiler SPDisplaysDataType -json\");\n const data = JSON.parse(stdout);\n const displays: DisplayInfo[] = [];\n\n if (data.SPDisplaysDataType?.[0]) {\n const gpuInfo = data.SPDisplaysDataType[0];\n const items: Array<{ native_resolution?: string; _name?: string }> = gpuInfo._items || [];\n\n items.forEach((item, index) => {\n const resolution = item.native_resolution;\n if (resolution) {\n const match = resolution.match(/(\\d+) x (\\d+)/);\n if (match) {\n displays.push({\n id: `display-${index}`,\n name: item._name || `Display ${index + 1}`,\n width: parseInt(match[1], 10),\n height: parseInt(match[2], 10),\n x: 0,\n y: 0,\n isPrimary: index === 0,\n });\n }\n }\n });\n }\n\n return displays;\n } else if (platform === \"linux\") {\n // Linux: Use xrandr\n const { stdout } = await execAsync(\"xrandr --query\");\n const displays: DisplayInfo[] = [];\n const lines = stdout.split(\"\\n\");\n\n for (const line of lines) {\n if (line.includes(\" connected\")) {\n const match = line.match(/^(\\S+) connected (?:primary )?(\\d+)x(\\d+)\\+(\\d+)\\+(\\d+)/);\n if (match) {\n displays.push({\n id: match[1],\n name: match[1],\n width: parseInt(match[2], 10),\n height: parseInt(match[3], 10),\n x: parseInt(match[4], 10),\n y: parseInt(match[5], 10),\n isPrimary: line.includes(\"primary\"),\n });\n }\n }\n }\n\n return displays;\n } else if (platform === \"win32\") {\n // Windows: Use wmic\n const { stdout } = await execAsync(\n \"wmic path Win32_DesktopMonitor get DeviceID,ScreenWidth,ScreenHeight /format:csv\"\n );\n const displays: DisplayInfo[] = [];\n const lines = stdout.trim().split(\"\\n\").slice(2); // Skip headers\n\n lines.forEach((line, index) => {\n const parts = line.split(\",\");\n if (parts.length >= 4) {\n const width = parseInt(parts[2], 10);\n const height = parseInt(parts[3], 10);\n if (!Number.isNaN(width) && !Number.isNaN(height)) {\n displays.push({\n id: parts[1],\n name: parts[1] || `Display ${index + 1}`,\n width,\n height,\n x: 0,\n y: 0,\n isPrimary: index === 0,\n });\n }\n }\n });\n\n return displays.length > 0\n ? displays\n : [\n {\n id: \"primary\",\n name: \"Primary Display\",\n width: 1920,\n height: 1080,\n x: 0,\n y: 0,\n isPrimary: true,\n },\n ];\n }\n } catch (error) {\n logger.error(\"[ScreenCaptureWorker] Failed to get display info:\", error);\n }\n\n // Fallback\n return [\n {\n id: \"default\",\n name: \"Default Display\",\n width: 1920,\n height: 1080,\n x: 0,\n y: 0,\n isPrimary: true,\n },\n ];\n }\n\n async run(): Promise<void> {\n await this.initialize();\n\n logger.info(\"[ScreenCaptureWorker] Starting capture loop...\");\n\n while (this.isRunning) {\n const startTime = Date.now();\n\n try {\n await this.captureFrame();\n this.frameCount++;\n\n // Report FPS every second\n const now = Date.now();\n if (now - this.lastFPSReport >= 1000) {\n const fps = this.frameCount / ((now - this.lastFPSReport) / 1000);\n logger.info(\n `[ScreenCaptureWorker] FPS: ${fps.toFixed(2)}, Display: ${this.currentDisplayIndex}`\n );\n\n parentPort?.postMessage({\n type: \"fps\",\n fps,\n frameCount: this.frameCount,\n displayIndex: this.currentDisplayIndex,\n });\n\n this.frameCount = 0;\n this.lastFPSReport = now;\n }\n\n // Cycle through displays if configured\n if (this.config.captureAllDisplays && this.displays.length > 1) {\n this.currentDisplayIndex = (this.currentDisplayIndex + 1) % this.displays.length;\n }\n\n // Target FPS limiting\n if (this.config.targetFPS) {\n const frameTime = 1000 / this.config.targetFPS;\n const elapsed = Date.now() - startTime;\n if (elapsed < frameTime) {\n await new Promise((resolve) => setTimeout(resolve, frameTime - elapsed));\n }\n }\n } catch (error) {\n logger.error(\"[ScreenCaptureWorker] Capture error:\", error);\n await new Promise((resolve) => setTimeout(resolve, 100)); // Brief pause on error\n }\n }\n }\n\n private async captureFrame(): Promise<void> {\n const display = this.displays[this.currentDisplayIndex];\n const tempFile = path.join(\n process.cwd(),\n `temp_screen_${Date.now()}_${this.currentDisplayIndex}.png`\n );\n\n try {\n // Capture the screen\n await this.captureScreenToFile(tempFile, display);\n\n // Load and process the image\n const imageBuffer = await fs.readFile(tempFile);\n const image = sharp(imageBuffer);\n const metadata = await image.metadata();\n\n const width = metadata.width || display.width;\n const height = metadata.height || display.height;\n\n // Convert to raw RGBA for shared buffer\n const rawData = await image.ensureAlpha().raw().toBuffer();\n\n // Wait for write lock\n while (Atomics.compareExchange(this.atomicState, this.WRITE_LOCK_INDEX, 0, 1) !== 0) {\n // Spin wait - in practice this should be very brief\n }\n\n try {\n // Write metadata\n Atomics.store(this.atomicState, this.WIDTH_INDEX, width);\n Atomics.store(this.atomicState, this.HEIGHT_INDEX, height);\n Atomics.store(this.atomicState, this.DISPLAY_INDEX, this.currentDisplayIndex);\n Atomics.store(this.atomicState, this.TIMESTAMP_INDEX, Date.now());\n\n // Write image data\n const maxDataSize = this.sharedBuffer.byteLength - this.DATA_OFFSET;\n const dataSize = Math.min(rawData.length, maxDataSize);\n\n for (let i = 0; i < dataSize; i++) {\n this.dataView.setUint8(this.DATA_OFFSET + i, rawData[i]);\n }\n\n // Update frame ID (signals new frame available)\n Atomics.add(this.atomicState, this.FRAME_ID_INDEX, 1);\n } finally {\n // Release write lock\n Atomics.store(this.atomicState, this.WRITE_LOCK_INDEX, 0);\n }\n\n // Clean up temp file\n await fs.unlink(tempFile).catch(() => {});\n } catch (error) {\n // Clean up temp file on error\n await fs.unlink(tempFile).catch(() => {});\n throw error;\n }\n }\n\n private async captureScreenToFile(outputPath: string, display: DisplayInfo): Promise<void> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // macOS: Use screencapture with display index\n const displayArg = this.currentDisplayIndex > 0 ? `-D ${this.currentDisplayIndex + 1}` : \"\";\n await execAsync(`screencapture -x ${displayArg} \"${outputPath}\"`);\n } else if (platform === \"linux\") {\n // Linux: Use scrot with geometry for specific display\n if (display.x !== 0 || display.y !== 0) {\n // Multi-monitor setup\n await execAsync(\n `scrot -a ${display.x},${display.y},${display.width},${display.height} \"${outputPath}\"`\n );\n } else {\n await execAsync(`scrot \"${outputPath}\"`);\n }\n } else if (platform === \"win32\") {\n // Windows: PowerShell script for specific monitor\n const script = `\n Add-Type -AssemblyName System.Windows.Forms;\n Add-Type -AssemblyName System.Drawing;\n $screens = [System.Windows.Forms.Screen]::AllScreens;\n $screen = $screens[${this.currentDisplayIndex}];\n $bounds = $screen.Bounds;\n $bitmap = New-Object System.Drawing.Bitmap $bounds.Width, $bounds.Height;\n $graphics = [System.Drawing.Graphics]::FromImage($bitmap);\n $graphics.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size);\n $bitmap.Save('${outputPath.replace(/\\\\/g, \"\\\\\\\\\")}');\n $graphics.Dispose();\n $bitmap.Dispose();\n `;\n await execAsync(`powershell -Command \"${script.replace(/\\n/g, \" \")}\"`);\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Screen capture failed: ${errorMessage}`);\n }\n }\n\n stop(): void {\n this.isRunning = false;\n }\n}\n\n// Worker entry point\nif (parentPort) {\n const { config, sharedBuffer } = workerData;\n const worker = new ScreenCaptureWorker(config, sharedBuffer);\n\n // Handle messages from main thread\n parentPort.on(\"message\", (msg) => {\n if (msg.type === \"stop\") {\n worker.stop();\n }\n });\n\n // Run the worker\n worker.run().catch((error) => {\n logger.error(\"[ScreenCaptureWorker] Fatal error:\", error);\n parentPort?.postMessage({ type: \"error\", error: error.message });\n process.exit(1);\n });\n}\n",
|
|
6
|
-
"import { parentPort } from \"node:worker_threads\";\n\n/**\n * Worker-safe logger that sends log messages to the main thread\n */\nexport const logger = {\n info: (message: string, ...args: unknown[]) => {\n const logMessage = {\n type: \"log\",\n level: \"info\",\n message,\n args,\n timestamp: new Date().toISOString(),\n };\n\n if (parentPort) {\n parentPort.postMessage(logMessage);\n } else {\n console.log(`[INFO] ${message}`, ...args);\n }\n },\n\n warn: (message: string, ...args: unknown[]) => {\n const logMessage = {\n type: \"log\",\n level: \"warn\",\n message,\n args,\n timestamp: new Date().toISOString(),\n };\n\n if (parentPort) {\n parentPort.postMessage(logMessage);\n } else {\n console.warn(`[WARN] ${message}`, ...args);\n }\n },\n\n error: (message: string, ...args: unknown[]) => {\n const logMessage = {\n type: \"log\",\n level: \"error\",\n message,\n args,\n timestamp: new Date().toISOString(),\n };\n\n if (parentPort) {\n parentPort.postMessage(logMessage);\n } else {\n console.error(`[ERROR] ${message}`, ...args);\n }\n },\n\n debug: (message: string, ...args: unknown[]) => {\n const logMessage = {\n type: \"log\",\n level: \"debug\",\n message,\n args,\n timestamp: new Date().toISOString(),\n };\n\n if (parentPort) {\n parentPort.postMessage(logMessage);\n } else {\n console.debug(`[DEBUG] ${message}`, ...args);\n }\n },\n};\n"
|
|
7
|
-
],
|
|
8
|
-
"mappings": "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",
|
|
9
|
-
"debugId": "91B84423455CE7E564756E2164756E21",
|
|
10
|
-
"names": []
|
|
11
|
-
}
|