@elizaos/plugin-vision 1.2.1 → 2.0.0-alpha.2

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 (106) hide show
  1. package/LICENSE +21 -0
  2. package/build.config.ts +53 -53
  3. package/dist/index.js +6716 -67
  4. package/dist/index.js.map +33 -1
  5. package/dist/workers/florence2-worker.js +111763 -307
  6. package/dist/workers/florence2-worker.js.map +92 -1
  7. package/dist/workers/ocr-worker.js +119177 -339
  8. package/dist/workers/ocr-worker.js.map +137 -1
  9. package/dist/workers/screen-capture-worker.js +350 -418
  10. package/dist/workers/screen-capture-worker.js.map +11 -1
  11. package/package.json +15 -20
  12. package/README.md +0 -270
  13. package/dist/action.d.ts +0 -8
  14. package/dist/action.js +0 -1212
  15. package/dist/action.js.map +0 -1
  16. package/dist/audio-capture-stream.d.ts +0 -42
  17. package/dist/audio-capture-stream.js +0 -516
  18. package/dist/audio-capture-stream.js.map +0 -1
  19. package/dist/audio-capture.d.ts +0 -25
  20. package/dist/audio-capture.js +0 -412
  21. package/dist/audio-capture.js.map +0 -1
  22. package/dist/basic.test.d.ts +0 -1
  23. package/dist/basic.test.js +0 -97
  24. package/dist/basic.test.js.map +0 -1
  25. package/dist/config.d.ts +0 -73
  26. package/dist/config.js +0 -254
  27. package/dist/config.js.map +0 -1
  28. package/dist/entity-tracker.d.ts +0 -32
  29. package/dist/entity-tracker.js +0 -361
  30. package/dist/entity-tracker.js.map +0 -1
  31. package/dist/errors.d.ts +0 -67
  32. package/dist/errors.js +0 -395
  33. package/dist/errors.js.map +0 -1
  34. package/dist/face-recognition.d.ts +0 -31
  35. package/dist/face-recognition.js +0 -332
  36. package/dist/face-recognition.js.map +0 -1
  37. package/dist/florence2-local.d.ts +0 -25
  38. package/dist/florence2-local.js +0 -280
  39. package/dist/florence2-local.js.map +0 -1
  40. package/dist/florence2-model.d.ts +0 -36
  41. package/dist/florence2-model.js +0 -503
  42. package/dist/florence2-model.js.map +0 -1
  43. package/dist/index.d.ts +0 -3
  44. package/dist/ocr-service-real.d.ts +0 -32
  45. package/dist/ocr-service-real.js +0 -396
  46. package/dist/ocr-service-real.js.map +0 -1
  47. package/dist/ocr-service.d.ts +0 -28
  48. package/dist/ocr-service.js +0 -216
  49. package/dist/ocr-service.js.map +0 -1
  50. package/dist/provider.d.ts +0 -2
  51. package/dist/provider.js +0 -285
  52. package/dist/provider.js.map +0 -1
  53. package/dist/screen-capture.d.ts +0 -16
  54. package/dist/screen-capture.js +0 -302
  55. package/dist/screen-capture.js.map +0 -1
  56. package/dist/service.d.ts +0 -73
  57. package/dist/service.js +0 -1662
  58. package/dist/service.js.map +0 -1
  59. package/dist/tests/e2e/index.d.ts +0 -8
  60. package/dist/tests/e2e/index.js +0 -33
  61. package/dist/tests/e2e/index.js.map +0 -1
  62. package/dist/tests/e2e/run-local.d.ts +0 -2
  63. package/dist/tests/e2e/run-local.js +0 -166
  64. package/dist/tests/e2e/run-local.js.map +0 -1
  65. package/dist/tests/e2e/screen-vision.d.ts +0 -11
  66. package/dist/tests/e2e/screen-vision.js +0 -384
  67. package/dist/tests/e2e/screen-vision.js.map +0 -1
  68. package/dist/tests/e2e/vision-autonomy.d.ts +0 -11
  69. package/dist/tests/e2e/vision-autonomy.js +0 -375
  70. package/dist/tests/e2e/vision-autonomy.js.map +0 -1
  71. package/dist/tests/e2e/vision-basic.d.ts +0 -11
  72. package/dist/tests/e2e/vision-basic.js +0 -434
  73. package/dist/tests/e2e/vision-basic.js.map +0 -1
  74. package/dist/tests/e2e/vision-capture-log.d.ts +0 -11
  75. package/dist/tests/e2e/vision-capture-log.js +0 -302
  76. package/dist/tests/e2e/vision-capture-log.js.map +0 -1
  77. package/dist/tests/e2e/vision-runtime.d.ts +0 -11
  78. package/dist/tests/e2e/vision-runtime.js +0 -357
  79. package/dist/tests/e2e/vision-runtime.js.map +0 -1
  80. package/dist/tests/e2e/vision-worker-tests.d.ts +0 -11
  81. package/dist/tests/e2e/vision-worker-tests.js +0 -466
  82. package/dist/tests/e2e/vision-worker-tests.js.map +0 -1
  83. package/dist/tests/test-pattern-generator.d.ts +0 -40
  84. package/dist/tests/test-pattern-generator.js +0 -191
  85. package/dist/tests/test-pattern-generator.js.map +0 -1
  86. package/dist/tests.d.ts +0 -3
  87. package/dist/tests.js +0 -11
  88. package/dist/tests.js.map +0 -1
  89. package/dist/types.d.ts +0 -222
  90. package/dist/types.js +0 -16
  91. package/dist/types.js.map +0 -1
  92. package/dist/vision-models.d.ts +0 -47
  93. package/dist/vision-models.js +0 -501
  94. package/dist/vision-models.js.map +0 -1
  95. package/dist/vision-worker-manager.d.ts +0 -61
  96. package/dist/vision-worker-manager.js +0 -668
  97. package/dist/vision-worker-manager.js.map +0 -1
  98. package/dist/workers/florence2-worker-simple.d.ts +0 -13
  99. package/dist/workers/florence2-worker-simple.js +0 -121
  100. package/dist/workers/florence2-worker-simple.js.map +0 -1
  101. package/dist/workers/florence2-worker.d.ts +0 -1
  102. package/dist/workers/ocr-worker.d.ts +0 -1
  103. package/dist/workers/screen-capture-worker.d.ts +0 -1
  104. package/dist/workers/worker-logger.d.ts +0 -9
  105. package/dist/workers/worker-logger.js +0 -95
  106. package/dist/workers/worker-logger.js.map +0 -1
@@ -1,427 +1,359 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
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;
10
16
  };
11
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
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
+ });
37
26
  };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- var worker_threads_1 = require("worker_threads");
40
- var child_process_1 = require("child_process");
41
- var util_1 = require("util");
42
- var fs = require("fs/promises");
43
- var path = require("path");
44
- var sharp_1 = require("sharp");
45
- var worker_logger_1 = require("./worker-logger");
46
- var execAsync = (0, util_1.promisify)(child_process_1.exec);
47
- var ScreenCaptureWorker = /** @class */ (function () {
48
- function ScreenCaptureWorker(config, sharedBuffer) {
49
- this.isRunning = true;
50
- this.frameCount = 0;
51
- this.lastFPSReport = Date.now();
52
- this.displays = [];
53
- this.currentDisplayIndex = 0;
54
- // Atomic indices
55
- this.FRAME_ID_INDEX = 0;
56
- this.WRITE_LOCK_INDEX = 1;
57
- this.WIDTH_INDEX = 2;
58
- this.HEIGHT_INDEX = 3;
59
- this.DISPLAY_INDEX = 4;
60
- this.TIMESTAMP_INDEX = 5;
61
- this.DATA_OFFSET = 24; // 6 * 4 bytes for metadata
62
- this.config = config;
63
- this.sharedBuffer = sharedBuffer;
64
- this.dataView = new DataView(sharedBuffer);
65
- this.atomicState = new Int32Array(sharedBuffer, 0, 6);
66
- }
67
- ScreenCaptureWorker.prototype.initialize = function () {
68
- return __awaiter(this, void 0, void 0, function () {
69
- var _a;
70
- return __generator(this, function (_b) {
71
- switch (_b.label) {
72
- case 0:
73
- // Get display information
74
- _a = this;
75
- return [4 /*yield*/, this.getDisplays()];
76
- case 1:
77
- // Get display information
78
- _a.displays = _b.sent();
79
- if (this.displays.length === 0) {
80
- throw new Error('No displays found');
81
- }
82
- // Set initial display
83
- if (this.config.displayIndex !== undefined && this.config.displayIndex < this.displays.length) {
84
- this.currentDisplayIndex = this.config.displayIndex;
85
- }
86
- worker_logger_1.logger.info("[ScreenCaptureWorker] Initialized with ".concat(this.displays.length, " displays"));
87
- this.displays.forEach(function (d, i) {
88
- worker_logger_1.logger.info(" Display ".concat(i, ": ").concat(d.name, " (").concat(d.width, "x").concat(d.height, ") ").concat(d.isPrimary ? '[PRIMARY]' : ''));
89
- });
90
- return [2 /*return*/];
91
- }
92
- });
93
- });
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()
94
46
  };
95
- ScreenCaptureWorker.prototype.getDisplays = function () {
96
- return __awaiter(this, void 0, void 0, function () {
97
- var platform, stdout, data, displays_1, gpuInfo, items, stdout, displays, lines, _i, lines_1, line, match, stdout, displays_2, lines, error_1;
98
- return __generator(this, function (_a) {
99
- switch (_a.label) {
100
- case 0:
101
- platform = process.platform;
102
- _a.label = 1;
103
- case 1:
104
- _a.trys.push([1, 8, , 9]);
105
- if (!(platform === 'darwin')) return [3 /*break*/, 3];
106
- return [4 /*yield*/, execAsync('system_profiler SPDisplaysDataType -json')];
107
- case 2:
108
- stdout = (_a.sent()).stdout;
109
- data = JSON.parse(stdout);
110
- displays_1 = [];
111
- if (data.SPDisplaysDataType && data.SPDisplaysDataType[0]) {
112
- gpuInfo = data.SPDisplaysDataType[0];
113
- items = gpuInfo._items || [];
114
- items.forEach(function (item, index) {
115
- var resolution = item.native_resolution;
116
- if (resolution) {
117
- var match = resolution.match(/(\d+) x (\d+)/);
118
- if (match) {
119
- displays_1.push({
120
- id: "display-".concat(index),
121
- name: item._name || "Display ".concat(index + 1),
122
- width: parseInt(match[1], 10),
123
- height: parseInt(match[2], 10),
124
- x: 0,
125
- y: 0,
126
- isPrimary: index === 0,
127
- });
128
- }
129
- }
130
- });
131
- }
132
- return [2 /*return*/, displays_1];
133
- case 3:
134
- if (!(platform === 'linux')) return [3 /*break*/, 5];
135
- return [4 /*yield*/, execAsync('xrandr --query')];
136
- case 4:
137
- stdout = (_a.sent()).stdout;
138
- displays = [];
139
- lines = stdout.split('\n');
140
- for (_i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
141
- line = lines_1[_i];
142
- if (line.includes(' connected')) {
143
- match = line.match(/^(\S+) connected (?:primary )?(\d+)x(\d+)\+(\d+)\+(\d+)/);
144
- if (match) {
145
- displays.push({
146
- id: match[1],
147
- name: match[1],
148
- width: parseInt(match[2], 10),
149
- height: parseInt(match[3], 10),
150
- x: parseInt(match[4], 10),
151
- y: parseInt(match[5], 10),
152
- isPrimary: line.includes('primary'),
153
- });
154
- }
155
- }
156
- }
157
- return [2 /*return*/, displays];
158
- case 5:
159
- if (!(platform === 'win32')) return [3 /*break*/, 7];
160
- return [4 /*yield*/, execAsync('wmic path Win32_DesktopMonitor get DeviceID,ScreenWidth,ScreenHeight /format:csv')];
161
- case 6:
162
- stdout = (_a.sent()).stdout;
163
- displays_2 = [];
164
- lines = stdout.trim().split('\n').slice(2);
165
- lines.forEach(function (line, index) {
166
- var parts = line.split(',');
167
- if (parts.length >= 4) {
168
- var width = parseInt(parts[2], 10);
169
- var height = parseInt(parts[3], 10);
170
- if (!isNaN(width) && !isNaN(height)) {
171
- displays_2.push({
172
- id: parts[1],
173
- name: parts[1] || "Display ".concat(index + 1),
174
- width: width,
175
- height: height,
176
- x: 0,
177
- y: 0,
178
- isPrimary: index === 0,
179
- });
180
- }
181
- }
182
- });
183
- return [2 /*return*/, displays_2.length > 0
184
- ? displays_2
185
- : [
186
- {
187
- id: 'primary',
188
- name: 'Primary Display',
189
- width: 1920,
190
- height: 1080,
191
- x: 0,
192
- y: 0,
193
- isPrimary: true,
194
- },
195
- ]];
196
- case 7: return [3 /*break*/, 9];
197
- case 8:
198
- error_1 = _a.sent();
199
- worker_logger_1.logger.error('[ScreenCaptureWorker] Failed to get display info:', error_1);
200
- return [3 /*break*/, 9];
201
- case 9:
202
- // Fallback
203
- return [2 /*return*/, [
204
- {
205
- id: 'default',
206
- name: 'Default Display',
207
- width: 1920,
208
- height: 1080,
209
- x: 0,
210
- y: 0,
211
- isPrimary: true,
212
- },
213
- ]];
214
- }
215
- });
216
- });
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()
217
60
  };
218
- ScreenCaptureWorker.prototype.run = function () {
219
- return __awaiter(this, void 0, void 0, function () {
220
- var _loop_1, this_1;
221
- return __generator(this, function (_a) {
222
- switch (_a.label) {
223
- case 0: return [4 /*yield*/, this.initialize()];
224
- case 1:
225
- _a.sent();
226
- worker_logger_1.logger.info('[ScreenCaptureWorker] Starting capture loop...');
227
- _loop_1 = function () {
228
- var startTime, now, fps, frameTime_1, elapsed_1, error_2;
229
- return __generator(this, function (_b) {
230
- switch (_b.label) {
231
- case 0:
232
- startTime = Date.now();
233
- _b.label = 1;
234
- case 1:
235
- _b.trys.push([1, 5, , 7]);
236
- return [4 /*yield*/, this_1.captureFrame()];
237
- case 2:
238
- _b.sent();
239
- this_1.frameCount++;
240
- now = Date.now();
241
- if (now - this_1.lastFPSReport >= 1000) {
242
- fps = this_1.frameCount / ((now - this_1.lastFPSReport) / 1000);
243
- worker_logger_1.logger.info("[ScreenCaptureWorker] FPS: ".concat(fps.toFixed(2), ", Display: ").concat(this_1.currentDisplayIndex));
244
- worker_threads_1.parentPort === null || worker_threads_1.parentPort === void 0 ? void 0 : worker_threads_1.parentPort.postMessage({
245
- type: 'fps',
246
- fps: fps,
247
- frameCount: this_1.frameCount,
248
- displayIndex: this_1.currentDisplayIndex,
249
- });
250
- this_1.frameCount = 0;
251
- this_1.lastFPSReport = now;
252
- }
253
- // Cycle through displays if configured
254
- if (this_1.config.captureAllDisplays && this_1.displays.length > 1) {
255
- this_1.currentDisplayIndex = (this_1.currentDisplayIndex + 1) % this_1.displays.length;
256
- }
257
- if (!this_1.config.targetFPS) return [3 /*break*/, 4];
258
- frameTime_1 = 1000 / this_1.config.targetFPS;
259
- elapsed_1 = Date.now() - startTime;
260
- if (!(elapsed_1 < frameTime_1)) return [3 /*break*/, 4];
261
- return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, frameTime_1 - elapsed_1); })];
262
- case 3:
263
- _b.sent();
264
- _b.label = 4;
265
- case 4: return [3 /*break*/, 7];
266
- case 5:
267
- error_2 = _b.sent();
268
- worker_logger_1.logger.error('[ScreenCaptureWorker] Capture error:', error_2);
269
- return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 100); })];
270
- case 6:
271
- _b.sent(); // Brief pause on error
272
- return [3 /*break*/, 7];
273
- case 7: return [2 /*return*/];
274
- }
275
- });
276
- };
277
- this_1 = this;
278
- _a.label = 2;
279
- case 2:
280
- if (!this.isRunning) return [3 /*break*/, 4];
281
- return [5 /*yield**/, _loop_1()];
282
- case 3:
283
- _a.sent();
284
- return [3 /*break*/, 2];
285
- case 4: return [2 /*return*/];
286
- }
287
- });
288
- });
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()
289
74
  };
290
- ScreenCaptureWorker.prototype.captureFrame = function () {
291
- return __awaiter(this, void 0, void 0, function () {
292
- var display, tempFile, imageBuffer, image, metadata, width, height, rawData, maxDataSize, dataSize, i, error_3;
293
- return __generator(this, function (_a) {
294
- switch (_a.label) {
295
- case 0:
296
- display = this.displays[this.currentDisplayIndex];
297
- tempFile = path.join(process.cwd(), "temp_screen_".concat(Date.now(), "_").concat(this.currentDisplayIndex, ".png"));
298
- _a.label = 1;
299
- case 1:
300
- _a.trys.push([1, 7, , 9]);
301
- // Capture the screen
302
- return [4 /*yield*/, this.captureScreenToFile(tempFile, display)];
303
- case 2:
304
- // Capture the screen
305
- _a.sent();
306
- return [4 /*yield*/, fs.readFile(tempFile)];
307
- case 3:
308
- imageBuffer = _a.sent();
309
- image = (0, sharp_1.default)(imageBuffer);
310
- return [4 /*yield*/, image.metadata()];
311
- case 4:
312
- metadata = _a.sent();
313
- width = metadata.width || display.width;
314
- height = metadata.height || display.height;
315
- return [4 /*yield*/, image.ensureAlpha().raw().toBuffer()];
316
- case 5:
317
- rawData = _a.sent();
318
- // Wait for write lock
319
- while (Atomics.compareExchange(this.atomicState, this.WRITE_LOCK_INDEX, 0, 1) !== 0) {
320
- // Spin wait - in practice this should be very brief
321
- }
322
- try {
323
- // Write metadata
324
- Atomics.store(this.atomicState, this.WIDTH_INDEX, width);
325
- Atomics.store(this.atomicState, this.HEIGHT_INDEX, height);
326
- Atomics.store(this.atomicState, this.DISPLAY_INDEX, this.currentDisplayIndex);
327
- Atomics.store(this.atomicState, this.TIMESTAMP_INDEX, Date.now());
328
- maxDataSize = this.sharedBuffer.byteLength - this.DATA_OFFSET;
329
- dataSize = Math.min(rawData.length, maxDataSize);
330
- for (i = 0; i < dataSize; i++) {
331
- this.dataView.setUint8(this.DATA_OFFSET + i, rawData[i]);
332
- }
333
- // Update frame ID (signals new frame available)
334
- Atomics.add(this.atomicState, this.FRAME_ID_INDEX, 1);
335
- }
336
- finally {
337
- // Release write lock
338
- Atomics.store(this.atomicState, this.WRITE_LOCK_INDEX, 0);
339
- }
340
- // Clean up temp file
341
- return [4 /*yield*/, fs.unlink(tempFile).catch(function () { })];
342
- case 6:
343
- // Clean up temp file
344
- _a.sent();
345
- return [3 /*break*/, 9];
346
- case 7:
347
- error_3 = _a.sent();
348
- // Clean up temp file on error
349
- return [4 /*yield*/, fs.unlink(tempFile).catch(function () { })];
350
- case 8:
351
- // Clean up temp file on error
352
- _a.sent();
353
- throw error_3;
354
- case 9: return [2 /*return*/];
355
- }
356
- });
357
- });
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()
358
88
  };
359
- ScreenCaptureWorker.prototype.captureScreenToFile = function (outputPath, display) {
360
- return __awaiter(this, void 0, void 0, function () {
361
- var platform, displayArg, script, error_4;
362
- return __generator(this, function (_a) {
363
- switch (_a.label) {
364
- case 0:
365
- platform = process.platform;
366
- _a.label = 1;
367
- case 1:
368
- _a.trys.push([1, 11, , 12]);
369
- if (!(platform === 'darwin')) return [3 /*break*/, 3];
370
- displayArg = this.currentDisplayIndex > 0 ? "-D ".concat(this.currentDisplayIndex + 1) : '';
371
- return [4 /*yield*/, execAsync("screencapture -x ".concat(displayArg, " \"").concat(outputPath, "\""))];
372
- case 2:
373
- _a.sent();
374
- return [3 /*break*/, 10];
375
- case 3:
376
- if (!(platform === 'linux')) return [3 /*break*/, 8];
377
- if (!(display.x !== 0 || display.y !== 0)) return [3 /*break*/, 5];
378
- // Multi-monitor setup
379
- return [4 /*yield*/, execAsync("scrot -a ".concat(display.x, ",").concat(display.y, ",").concat(display.width, ",").concat(display.height, " \"").concat(outputPath, "\""))];
380
- case 4:
381
- // Multi-monitor setup
382
- _a.sent();
383
- return [3 /*break*/, 7];
384
- case 5: return [4 /*yield*/, execAsync("scrot \"".concat(outputPath, "\""))];
385
- case 6:
386
- _a.sent();
387
- _a.label = 7;
388
- case 7: return [3 /*break*/, 10];
389
- case 8:
390
- if (!(platform === 'win32')) return [3 /*break*/, 10];
391
- script = "\n Add-Type -AssemblyName System.Windows.Forms;\n Add-Type -AssemblyName System.Drawing;\n $screens = [System.Windows.Forms.Screen]::AllScreens;\n $screen = $screens[".concat(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('").concat(outputPath.replace(/\\/g, '\\\\'), "');\n $graphics.Dispose();\n $bitmap.Dispose();\n ");
392
- return [4 /*yield*/, execAsync("powershell -Command \"".concat(script.replace(/\n/g, ' '), "\""))];
393
- case 9:
394
- _a.sent();
395
- _a.label = 10;
396
- case 10: return [3 /*break*/, 12];
397
- case 11:
398
- error_4 = _a.sent();
399
- throw new Error("Screen capture failed: ".concat(error_4.message));
400
- case 12: return [2 /*return*/];
401
- }
402
- });
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
+ }
403
209
  });
404
- };
405
- ScreenCaptureWorker.prototype.stop = function () {
406
- this.isRunning = false;
407
- };
408
- return ScreenCaptureWorker;
409
- }());
410
- // Worker entry point
411
- if (worker_threads_1.parentPort) {
412
- var config = worker_threads_1.workerData.config, sharedBuffer = worker_threads_1.workerData.sharedBuffer;
413
- var worker_1 = new ScreenCaptureWorker(config, sharedBuffer);
414
- // Handle messages from main thread
415
- worker_threads_1.parentPort.on('message', function (msg) {
416
- if (msg.type === 'stop') {
417
- worker_1.stop();
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;
418
257
  }
419
- });
420
- // Run the worker
421
- worker_1.run().catch(function (error) {
422
- worker_logger_1.logger.error('[ScreenCaptureWorker] Fatal error:', error);
423
- worker_threads_1.parentPort === null || worker_threads_1.parentPort === void 0 ? void 0 : worker_threads_1.parentPort.postMessage({ type: 'error', error: error.message });
424
- process.exit(1);
425
- });
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
+ });
426
356
  }
427
- //# sourceMappingURL=screen-capture-worker.js.map
357
+
358
+ //# debugId=91B84423455CE7E564756E2164756E21
359
+ //# sourceMappingURL=screen-capture-worker.js.map