@elizaos/plugin-vision 1.2.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 (106) hide show
  1. package/.npmignore +5 -0
  2. package/README.md +270 -0
  3. package/build.config.ts +70 -0
  4. package/dist/action.d.ts +8 -0
  5. package/dist/action.js +1212 -0
  6. package/dist/action.js.map +1 -0
  7. package/dist/audio-capture-stream.d.ts +42 -0
  8. package/dist/audio-capture-stream.js +516 -0
  9. package/dist/audio-capture-stream.js.map +1 -0
  10. package/dist/audio-capture.d.ts +25 -0
  11. package/dist/audio-capture.js +412 -0
  12. package/dist/audio-capture.js.map +1 -0
  13. package/dist/basic.test.d.ts +1 -0
  14. package/dist/basic.test.js +97 -0
  15. package/dist/basic.test.js.map +1 -0
  16. package/dist/config.d.ts +73 -0
  17. package/dist/config.js +254 -0
  18. package/dist/config.js.map +1 -0
  19. package/dist/entity-tracker.d.ts +32 -0
  20. package/dist/entity-tracker.js +361 -0
  21. package/dist/entity-tracker.js.map +1 -0
  22. package/dist/errors.d.ts +67 -0
  23. package/dist/errors.js +395 -0
  24. package/dist/errors.js.map +1 -0
  25. package/dist/face-recognition.d.ts +31 -0
  26. package/dist/face-recognition.js +332 -0
  27. package/dist/face-recognition.js.map +1 -0
  28. package/dist/florence2-local.d.ts +25 -0
  29. package/dist/florence2-local.js +280 -0
  30. package/dist/florence2-local.js.map +1 -0
  31. package/dist/florence2-model.d.ts +36 -0
  32. package/dist/florence2-model.js +503 -0
  33. package/dist/florence2-model.js.map +1 -0
  34. package/dist/index.d.ts +3 -0
  35. package/dist/index.js +73 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/ocr-service-real.d.ts +32 -0
  38. package/dist/ocr-service-real.js +396 -0
  39. package/dist/ocr-service-real.js.map +1 -0
  40. package/dist/ocr-service.d.ts +28 -0
  41. package/dist/ocr-service.js +216 -0
  42. package/dist/ocr-service.js.map +1 -0
  43. package/dist/provider.d.ts +2 -0
  44. package/dist/provider.js +285 -0
  45. package/dist/provider.js.map +1 -0
  46. package/dist/screen-capture.d.ts +16 -0
  47. package/dist/screen-capture.js +302 -0
  48. package/dist/screen-capture.js.map +1 -0
  49. package/dist/service.d.ts +73 -0
  50. package/dist/service.js +1662 -0
  51. package/dist/service.js.map +1 -0
  52. package/dist/tests/e2e/index.d.ts +8 -0
  53. package/dist/tests/e2e/index.js +33 -0
  54. package/dist/tests/e2e/index.js.map +1 -0
  55. package/dist/tests/e2e/run-local.d.ts +2 -0
  56. package/dist/tests/e2e/run-local.js +166 -0
  57. package/dist/tests/e2e/run-local.js.map +1 -0
  58. package/dist/tests/e2e/screen-vision.d.ts +11 -0
  59. package/dist/tests/e2e/screen-vision.js +384 -0
  60. package/dist/tests/e2e/screen-vision.js.map +1 -0
  61. package/dist/tests/e2e/vision-autonomy.d.ts +11 -0
  62. package/dist/tests/e2e/vision-autonomy.js +375 -0
  63. package/dist/tests/e2e/vision-autonomy.js.map +1 -0
  64. package/dist/tests/e2e/vision-basic.d.ts +11 -0
  65. package/dist/tests/e2e/vision-basic.js +434 -0
  66. package/dist/tests/e2e/vision-basic.js.map +1 -0
  67. package/dist/tests/e2e/vision-capture-log.d.ts +11 -0
  68. package/dist/tests/e2e/vision-capture-log.js +302 -0
  69. package/dist/tests/e2e/vision-capture-log.js.map +1 -0
  70. package/dist/tests/e2e/vision-runtime.d.ts +11 -0
  71. package/dist/tests/e2e/vision-runtime.js +357 -0
  72. package/dist/tests/e2e/vision-runtime.js.map +1 -0
  73. package/dist/tests/e2e/vision-worker-tests.d.ts +11 -0
  74. package/dist/tests/e2e/vision-worker-tests.js +466 -0
  75. package/dist/tests/e2e/vision-worker-tests.js.map +1 -0
  76. package/dist/tests/test-pattern-generator.d.ts +40 -0
  77. package/dist/tests/test-pattern-generator.js +191 -0
  78. package/dist/tests/test-pattern-generator.js.map +1 -0
  79. package/dist/tests.d.ts +3 -0
  80. package/dist/tests.js +11 -0
  81. package/dist/tests.js.map +1 -0
  82. package/dist/types.d.ts +222 -0
  83. package/dist/types.js +16 -0
  84. package/dist/types.js.map +1 -0
  85. package/dist/vision-models.d.ts +47 -0
  86. package/dist/vision-models.js +501 -0
  87. package/dist/vision-models.js.map +1 -0
  88. package/dist/vision-worker-manager.d.ts +61 -0
  89. package/dist/vision-worker-manager.js +668 -0
  90. package/dist/vision-worker-manager.js.map +1 -0
  91. package/dist/workers/florence2-worker-simple.d.ts +13 -0
  92. package/dist/workers/florence2-worker-simple.js +121 -0
  93. package/dist/workers/florence2-worker-simple.js.map +1 -0
  94. package/dist/workers/florence2-worker.d.ts +1 -0
  95. package/dist/workers/florence2-worker.js +328 -0
  96. package/dist/workers/florence2-worker.js.map +1 -0
  97. package/dist/workers/ocr-worker.d.ts +1 -0
  98. package/dist/workers/ocr-worker.js +354 -0
  99. package/dist/workers/ocr-worker.js.map +1 -0
  100. package/dist/workers/screen-capture-worker.d.ts +1 -0
  101. package/dist/workers/screen-capture-worker.js +427 -0
  102. package/dist/workers/screen-capture-worker.js.map +1 -0
  103. package/dist/workers/worker-logger.d.ts +9 -0
  104. package/dist/workers/worker-logger.js +95 -0
  105. package/dist/workers/worker-logger.js.map +1 -0
  106. package/package.json +100 -0
@@ -0,0 +1,361 @@
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
+ });
10
+ };
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
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.EntityTracker = void 0;
40
+ var core_1 = require("@elizaos/core");
41
+ var EntityTracker = /** @class */ (function () {
42
+ function EntityTracker(worldId) {
43
+ this.POSITION_THRESHOLD = 100; // pixels
44
+ this.MISSING_THRESHOLD = 5000; // 5 seconds
45
+ this.CLEANUP_THRESHOLD = 60000; // 1 minute
46
+ this.worldState = {
47
+ worldId: worldId,
48
+ entities: new Map(),
49
+ lastUpdate: Date.now(),
50
+ activeEntities: [],
51
+ recentlyLeft: [],
52
+ };
53
+ }
54
+ EntityTracker.prototype.updateEntities = function (detectedObjects, people, faceProfiles, // Maps person ID to face profile ID
55
+ runtime) {
56
+ return __awaiter(this, void 0, void 0, function () {
57
+ var currentTime, frameEntities, seenEntityIds, _i, people_1, person, entity, _a, detectedObjects_1, obj, entity;
58
+ return __generator(this, function (_b) {
59
+ switch (_b.label) {
60
+ case 0:
61
+ currentTime = Date.now();
62
+ frameEntities = [];
63
+ seenEntityIds = new Set();
64
+ _i = 0, people_1 = people;
65
+ _b.label = 1;
66
+ case 1:
67
+ if (!(_i < people_1.length)) return [3 /*break*/, 4];
68
+ person = people_1[_i];
69
+ return [4 /*yield*/, this.trackPerson(person, faceProfiles === null || faceProfiles === void 0 ? void 0 : faceProfiles.get(person.id), currentTime)];
70
+ case 2:
71
+ entity = _b.sent();
72
+ frameEntities.push(entity);
73
+ seenEntityIds.add(entity.id);
74
+ _b.label = 3;
75
+ case 3:
76
+ _i++;
77
+ return [3 /*break*/, 1];
78
+ case 4:
79
+ _a = 0, detectedObjects_1 = detectedObjects;
80
+ _b.label = 5;
81
+ case 5:
82
+ if (!(_a < detectedObjects_1.length)) return [3 /*break*/, 8];
83
+ obj = detectedObjects_1[_a];
84
+ if (!(obj.type !== 'person' && obj.type !== 'person-candidate')) return [3 /*break*/, 7];
85
+ return [4 /*yield*/, this.trackObject(obj, currentTime)];
86
+ case 6:
87
+ entity = _b.sent();
88
+ frameEntities.push(entity);
89
+ seenEntityIds.add(entity.id);
90
+ _b.label = 7;
91
+ case 7:
92
+ _a++;
93
+ return [3 /*break*/, 5];
94
+ case 8:
95
+ // Update world state
96
+ this.updateWorldState(seenEntityIds, currentTime);
97
+ if (!runtime) return [3 /*break*/, 10];
98
+ return [4 /*yield*/, this.syncWithRuntime(runtime, frameEntities)];
99
+ case 9:
100
+ _b.sent();
101
+ _b.label = 10;
102
+ case 10: return [2 /*return*/, frameEntities];
103
+ }
104
+ });
105
+ });
106
+ };
107
+ EntityTracker.prototype.trackPerson = function (person, faceProfileId, timestamp) {
108
+ return __awaiter(this, void 0, void 0, function () {
109
+ var matchedEntity, entityId, newEntity;
110
+ return __generator(this, function (_a) {
111
+ matchedEntity = this.findMatchingEntity(person.boundingBox, 'person', faceProfileId);
112
+ if (matchedEntity) {
113
+ // Update existing entity
114
+ matchedEntity.lastSeen = timestamp;
115
+ matchedEntity.lastPosition = person.boundingBox;
116
+ matchedEntity.appearances.push({
117
+ timestamp: timestamp,
118
+ boundingBox: person.boundingBox,
119
+ confidence: person.confidence,
120
+ });
121
+ // Update attributes
122
+ if (faceProfileId && !matchedEntity.attributes.faceId) {
123
+ matchedEntity.attributes.faceId = faceProfileId;
124
+ }
125
+ // Keep only last 100 appearances
126
+ if (matchedEntity.appearances.length > 100) {
127
+ matchedEntity.appearances = matchedEntity.appearances.slice(-100);
128
+ }
129
+ return [2 /*return*/, matchedEntity];
130
+ }
131
+ else {
132
+ entityId = "person-".concat(timestamp, "-").concat(Math.random().toString(36).substr(2, 9));
133
+ newEntity = {
134
+ id: entityId,
135
+ entityType: 'person',
136
+ firstSeen: timestamp,
137
+ lastSeen: timestamp,
138
+ lastPosition: person.boundingBox,
139
+ appearances: [
140
+ {
141
+ timestamp: timestamp,
142
+ boundingBox: person.boundingBox,
143
+ confidence: person.confidence,
144
+ },
145
+ ],
146
+ attributes: {
147
+ faceId: faceProfileId,
148
+ },
149
+ worldId: this.worldState.worldId,
150
+ };
151
+ this.worldState.entities.set(entityId, newEntity);
152
+ core_1.logger.info("[EntityTracker] New person entity created: ".concat(entityId));
153
+ return [2 /*return*/, newEntity];
154
+ }
155
+ return [2 /*return*/];
156
+ });
157
+ });
158
+ };
159
+ EntityTracker.prototype.trackObject = function (obj, timestamp) {
160
+ return __awaiter(this, void 0, void 0, function () {
161
+ var matchedEntity, entityId, newEntity;
162
+ return __generator(this, function (_a) {
163
+ matchedEntity = this.findMatchingEntity(obj.boundingBox, 'object');
164
+ if (matchedEntity) {
165
+ // Update existing entity
166
+ matchedEntity.lastSeen = timestamp;
167
+ matchedEntity.lastPosition = obj.boundingBox;
168
+ matchedEntity.appearances.push({
169
+ timestamp: timestamp,
170
+ boundingBox: obj.boundingBox,
171
+ confidence: obj.confidence,
172
+ });
173
+ // Keep only last 50 appearances for objects
174
+ if (matchedEntity.appearances.length > 50) {
175
+ matchedEntity.appearances = matchedEntity.appearances.slice(-50);
176
+ }
177
+ return [2 /*return*/, matchedEntity];
178
+ }
179
+ else {
180
+ entityId = "object-".concat(timestamp, "-").concat(Math.random().toString(36).substr(2, 9));
181
+ newEntity = {
182
+ id: entityId,
183
+ entityType: 'object',
184
+ firstSeen: timestamp,
185
+ lastSeen: timestamp,
186
+ lastPosition: obj.boundingBox,
187
+ appearances: [
188
+ {
189
+ timestamp: timestamp,
190
+ boundingBox: obj.boundingBox,
191
+ confidence: obj.confidence,
192
+ },
193
+ ],
194
+ attributes: {
195
+ objectType: obj.type,
196
+ },
197
+ worldId: this.worldState.worldId,
198
+ };
199
+ this.worldState.entities.set(entityId, newEntity);
200
+ core_1.logger.debug("[EntityTracker] New object entity created: ".concat(entityId, " (").concat(obj.type, ")"));
201
+ return [2 /*return*/, newEntity];
202
+ }
203
+ return [2 /*return*/];
204
+ });
205
+ });
206
+ };
207
+ EntityTracker.prototype.findMatchingEntity = function (boundingBox, entityType, faceProfileId) {
208
+ var currentTime = Date.now();
209
+ var bestMatch = null;
210
+ var minDistance = Infinity;
211
+ for (var _i = 0, _a = this.worldState.entities.values(); _i < _a.length; _i++) {
212
+ var entity = _a[_i];
213
+ // Skip if wrong type
214
+ if (entity.entityType !== entityType) {
215
+ continue;
216
+ }
217
+ // Skip if entity has been missing too long
218
+ if (currentTime - entity.lastSeen > this.MISSING_THRESHOLD) {
219
+ continue;
220
+ }
221
+ // If we have face ID, prioritize face matching for people
222
+ if (entityType === 'person' && faceProfileId && entity.attributes.faceId) {
223
+ if (entity.attributes.faceId === faceProfileId) {
224
+ return entity; // Direct face match
225
+ }
226
+ }
227
+ // Calculate position distance
228
+ var distance = this.calculateDistance(entity.lastPosition, boundingBox);
229
+ if (distance < this.POSITION_THRESHOLD && distance < minDistance) {
230
+ minDistance = distance;
231
+ bestMatch = entity;
232
+ }
233
+ }
234
+ return bestMatch;
235
+ };
236
+ EntityTracker.prototype.calculateDistance = function (box1, box2) {
237
+ var center1 = {
238
+ x: box1.x + box1.width / 2,
239
+ y: box1.y + box1.height / 2,
240
+ };
241
+ var center2 = {
242
+ x: box2.x + box2.width / 2,
243
+ y: box2.y + box2.height / 2,
244
+ };
245
+ return Math.sqrt(Math.pow(center1.x - center2.x, 2) + Math.pow(center1.y - center2.y, 2));
246
+ };
247
+ EntityTracker.prototype.updateWorldState = function (seenEntityIds, timestamp) {
248
+ var _this = this;
249
+ // Update active entities
250
+ this.worldState.activeEntities = Array.from(seenEntityIds);
251
+ this.worldState.lastUpdate = timestamp;
252
+ // Check for entities that left
253
+ for (var _i = 0, _a = this.worldState.entities; _i < _a.length; _i++) {
254
+ var _b = _a[_i], entityId = _b[0], entity = _b[1];
255
+ if (!seenEntityIds.has(entityId) && this.worldState.activeEntities.includes(entityId)) {
256
+ // Entity just left the scene
257
+ this.worldState.recentlyLeft.push({
258
+ entityId: entityId,
259
+ leftAt: timestamp,
260
+ lastPosition: entity.lastPosition,
261
+ });
262
+ core_1.logger.info("[EntityTracker] Entity left scene: ".concat(entityId));
263
+ }
264
+ }
265
+ // Clean up old "recently left" entries
266
+ this.worldState.recentlyLeft = this.worldState.recentlyLeft.filter(function (entry) { return timestamp - entry.leftAt < _this.CLEANUP_THRESHOLD; });
267
+ // Clean up very old entities
268
+ for (var _c = 0, _d = this.worldState.entities; _c < _d.length; _c++) {
269
+ var _e = _d[_c], entityId = _e[0], entity = _e[1];
270
+ if (timestamp - entity.lastSeen > this.CLEANUP_THRESHOLD * 10) {
271
+ this.worldState.entities.delete(entityId);
272
+ core_1.logger.debug("[EntityTracker] Cleaned up old entity: ".concat(entityId));
273
+ }
274
+ }
275
+ };
276
+ EntityTracker.prototype.syncWithRuntime = function (runtime, frameEntities) {
277
+ return __awaiter(this, void 0, void 0, function () {
278
+ var _i, frameEntities_1, entity, _elizaEntity;
279
+ return __generator(this, function (_a) {
280
+ try {
281
+ // Create or update entities in the runtime
282
+ for (_i = 0, frameEntities_1 = frameEntities; _i < frameEntities_1.length; _i++) {
283
+ entity = frameEntities_1[_i];
284
+ _elizaEntity = {
285
+ id: entity.id,
286
+ names: [entity.attributes.name || entity.id],
287
+ metadata: {
288
+ type: entity.entityType,
289
+ firstSeen: entity.firstSeen,
290
+ lastSeen: entity.lastSeen,
291
+ attributes: entity.attributes,
292
+ worldId: this.worldState.worldId,
293
+ },
294
+ agentId: runtime.agentId,
295
+ };
296
+ // For now, we'll just log the entity creation
297
+ // In a real implementation, this would integrate with runtime.createEntity
298
+ core_1.logger.debug("[EntityTracker] Would sync entity ".concat(entity.id, " with runtime"));
299
+ // TODO: When runtime supports entity management:
300
+ // const existing = await runtime.getEntity(entity.id as UUID);
301
+ // if (!existing) {
302
+ // await runtime.createEntity(elizaEntity);
303
+ // } else {
304
+ // await runtime.updateEntity({...});
305
+ // }
306
+ }
307
+ }
308
+ catch (error) {
309
+ core_1.logger.error('[EntityTracker] Failed to sync with runtime:', error);
310
+ }
311
+ return [2 /*return*/];
312
+ });
313
+ });
314
+ };
315
+ // Public API
316
+ EntityTracker.prototype.getWorldState = function () {
317
+ return this.worldState;
318
+ };
319
+ EntityTracker.prototype.getActiveEntities = function () {
320
+ var _this = this;
321
+ return this.worldState.activeEntities
322
+ .map(function (id) { return _this.worldState.entities.get(id); })
323
+ .filter(Boolean);
324
+ };
325
+ EntityTracker.prototype.getEntity = function (entityId) {
326
+ return this.worldState.entities.get(entityId);
327
+ };
328
+ EntityTracker.prototype.getRecentlyLeft = function () {
329
+ var _this = this;
330
+ return this.worldState.recentlyLeft
331
+ .map(function (entry) { return ({
332
+ entity: _this.worldState.entities.get(entry.entityId),
333
+ leftAt: entry.leftAt,
334
+ }); })
335
+ .filter(function (entry) { return entry.entity; });
336
+ };
337
+ // Name assignment
338
+ EntityTracker.prototype.assignNameToEntity = function (entityId, name) {
339
+ var entity = this.worldState.entities.get(entityId);
340
+ if (entity) {
341
+ entity.attributes.name = name;
342
+ core_1.logger.info("[EntityTracker] Assigned name \"".concat(name, "\" to entity ").concat(entityId));
343
+ return true;
344
+ }
345
+ return false;
346
+ };
347
+ // Get statistics
348
+ EntityTracker.prototype.getStatistics = function () {
349
+ var entities = Array.from(this.worldState.entities.values());
350
+ return {
351
+ totalEntities: entities.length,
352
+ activeEntities: this.worldState.activeEntities.length,
353
+ recentlyLeft: this.worldState.recentlyLeft.length,
354
+ people: entities.filter(function (e) { return e.entityType === 'person'; }).length,
355
+ objects: entities.filter(function (e) { return e.entityType === 'object'; }).length,
356
+ };
357
+ };
358
+ return EntityTracker;
359
+ }());
360
+ exports.EntityTracker = EntityTracker;
361
+ //# sourceMappingURL=entity-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-tracker.js","sourceRoot":"","sources":["../src/entity-tracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { logger, type IAgentRuntime, type UUID } from '@elizaos/core';\nimport type { TrackedEntity, WorldState, DetectedObject, PersonInfo, BoundingBox } from './types';\n\nexport class EntityTracker {\n private worldState: WorldState;\n private readonly POSITION_THRESHOLD = 100; // pixels\n private readonly MISSING_THRESHOLD = 5000; // 5 seconds\n private readonly CLEANUP_THRESHOLD = 60000; // 1 minute\n\n constructor(worldId: string) {\n this.worldState = {\n worldId,\n entities: new Map(),\n lastUpdate: Date.now(),\n activeEntities: [],\n recentlyLeft: [],\n };\n }\n\n async updateEntities(\n detectedObjects: DetectedObject[],\n people: PersonInfo[],\n faceProfiles?: Map<string, string>, // Maps person ID to face profile ID\n runtime?: IAgentRuntime\n ): Promise<TrackedEntity[]> {\n const currentTime = Date.now();\n const frameEntities: TrackedEntity[] = [];\n const seenEntityIds = new Set<string>();\n\n // Process detected people\n for (const person of people) {\n const entity = await this.trackPerson(person, faceProfiles?.get(person.id), currentTime);\n frameEntities.push(entity);\n seenEntityIds.add(entity.id);\n }\n\n // Process detected objects\n for (const obj of detectedObjects) {\n if (obj.type !== 'person' && obj.type !== 'person-candidate') {\n const entity = await this.trackObject(obj, currentTime);\n frameEntities.push(entity);\n seenEntityIds.add(entity.id);\n }\n }\n\n // Update world state\n this.updateWorldState(seenEntityIds, currentTime);\n\n // Store entities in runtime if available\n if (runtime) {\n await this.syncWithRuntime(runtime, frameEntities);\n }\n\n return frameEntities;\n }\n\n private async trackPerson(\n person: PersonInfo,\n faceProfileId: string | undefined,\n timestamp: number\n ): Promise<TrackedEntity> {\n // Try to match with existing entities\n const matchedEntity = this.findMatchingEntity(person.boundingBox, 'person', faceProfileId);\n\n if (matchedEntity) {\n // Update existing entity\n matchedEntity.lastSeen = timestamp;\n matchedEntity.lastPosition = person.boundingBox;\n matchedEntity.appearances.push({\n timestamp,\n boundingBox: person.boundingBox,\n confidence: person.confidence,\n });\n\n // Update attributes\n if (faceProfileId && !matchedEntity.attributes.faceId) {\n matchedEntity.attributes.faceId = faceProfileId;\n }\n\n // Keep only last 100 appearances\n if (matchedEntity.appearances.length > 100) {\n matchedEntity.appearances = matchedEntity.appearances.slice(-100);\n }\n\n return matchedEntity;\n } else {\n // Create new entity\n const entityId = `person-${timestamp}-${Math.random().toString(36).substr(2, 9)}`;\n const newEntity: TrackedEntity = {\n id: entityId,\n entityType: 'person',\n firstSeen: timestamp,\n lastSeen: timestamp,\n lastPosition: person.boundingBox,\n appearances: [\n {\n timestamp,\n boundingBox: person.boundingBox,\n confidence: person.confidence,\n },\n ],\n attributes: {\n faceId: faceProfileId,\n },\n worldId: this.worldState.worldId,\n };\n\n this.worldState.entities.set(entityId, newEntity);\n logger.info(`[EntityTracker] New person entity created: ${entityId}`);\n\n return newEntity;\n }\n }\n\n private async trackObject(obj: DetectedObject, timestamp: number): Promise<TrackedEntity> {\n // Try to match with existing entities\n const matchedEntity = this.findMatchingEntity(obj.boundingBox, 'object');\n\n if (matchedEntity) {\n // Update existing entity\n matchedEntity.lastSeen = timestamp;\n matchedEntity.lastPosition = obj.boundingBox;\n matchedEntity.appearances.push({\n timestamp,\n boundingBox: obj.boundingBox,\n confidence: obj.confidence,\n });\n\n // Keep only last 50 appearances for objects\n if (matchedEntity.appearances.length > 50) {\n matchedEntity.appearances = matchedEntity.appearances.slice(-50);\n }\n\n return matchedEntity;\n } else {\n // Create new entity\n const entityId = `object-${timestamp}-${Math.random().toString(36).substr(2, 9)}`;\n const newEntity: TrackedEntity = {\n id: entityId,\n entityType: 'object',\n firstSeen: timestamp,\n lastSeen: timestamp,\n lastPosition: obj.boundingBox,\n appearances: [\n {\n timestamp,\n boundingBox: obj.boundingBox,\n confidence: obj.confidence,\n },\n ],\n attributes: {\n objectType: obj.type,\n },\n worldId: this.worldState.worldId,\n };\n\n this.worldState.entities.set(entityId, newEntity);\n logger.debug(`[EntityTracker] New object entity created: ${entityId} (${obj.type})`);\n\n return newEntity;\n }\n }\n\n private findMatchingEntity(\n boundingBox: BoundingBox,\n entityType: 'person' | 'object',\n faceProfileId?: string\n ): TrackedEntity | null {\n const currentTime = Date.now();\n let bestMatch: TrackedEntity | null = null;\n let minDistance = Infinity;\n\n for (const entity of this.worldState.entities.values()) {\n // Skip if wrong type\n if (entity.entityType !== entityType) {\n continue;\n }\n\n // Skip if entity has been missing too long\n if (currentTime - entity.lastSeen > this.MISSING_THRESHOLD) {\n continue;\n }\n\n // If we have face ID, prioritize face matching for people\n if (entityType === 'person' && faceProfileId && entity.attributes.faceId) {\n if (entity.attributes.faceId === faceProfileId) {\n return entity; // Direct face match\n }\n }\n\n // Calculate position distance\n const distance = this.calculateDistance(entity.lastPosition, boundingBox);\n\n if (distance < this.POSITION_THRESHOLD && distance < minDistance) {\n minDistance = distance;\n bestMatch = entity;\n }\n }\n\n return bestMatch;\n }\n\n private calculateDistance(box1: BoundingBox, box2: BoundingBox): number {\n const center1 = {\n x: box1.x + box1.width / 2,\n y: box1.y + box1.height / 2,\n };\n const center2 = {\n x: box2.x + box2.width / 2,\n y: box2.y + box2.height / 2,\n };\n\n return Math.sqrt(Math.pow(center1.x - center2.x, 2) + Math.pow(center1.y - center2.y, 2));\n }\n\n private updateWorldState(seenEntityIds: Set<string>, timestamp: number): void {\n // Update active entities\n this.worldState.activeEntities = Array.from(seenEntityIds);\n this.worldState.lastUpdate = timestamp;\n\n // Check for entities that left\n for (const [entityId, entity] of this.worldState.entities) {\n if (!seenEntityIds.has(entityId) && this.worldState.activeEntities.includes(entityId)) {\n // Entity just left the scene\n this.worldState.recentlyLeft.push({\n entityId,\n leftAt: timestamp,\n lastPosition: entity.lastPosition,\n });\n\n logger.info(`[EntityTracker] Entity left scene: ${entityId}`);\n }\n }\n\n // Clean up old \"recently left\" entries\n this.worldState.recentlyLeft = this.worldState.recentlyLeft.filter(\n (entry) => timestamp - entry.leftAt < this.CLEANUP_THRESHOLD\n );\n\n // Clean up very old entities\n for (const [entityId, entity] of this.worldState.entities) {\n if (timestamp - entity.lastSeen > this.CLEANUP_THRESHOLD * 10) {\n this.worldState.entities.delete(entityId);\n logger.debug(`[EntityTracker] Cleaned up old entity: ${entityId}`);\n }\n }\n }\n\n private async syncWithRuntime(\n runtime: IAgentRuntime,\n frameEntities: TrackedEntity[]\n ): Promise<void> {\n try {\n // Create or update entities in the runtime\n for (const entity of frameEntities) {\n const _elizaEntity = {\n id: entity.id as UUID,\n names: [entity.attributes.name || entity.id],\n metadata: {\n type: entity.entityType,\n firstSeen: entity.firstSeen,\n lastSeen: entity.lastSeen,\n attributes: entity.attributes,\n worldId: this.worldState.worldId,\n },\n agentId: runtime.agentId,\n };\n\n // For now, we'll just log the entity creation\n // In a real implementation, this would integrate with runtime.createEntity\n logger.debug(`[EntityTracker] Would sync entity ${entity.id} with runtime`);\n\n // TODO: When runtime supports entity management:\n // const existing = await runtime.getEntity(entity.id as UUID);\n // if (!existing) {\n // await runtime.createEntity(elizaEntity);\n // } else {\n // await runtime.updateEntity({...});\n // }\n }\n } catch (error) {\n logger.error('[EntityTracker] Failed to sync with runtime:', error);\n }\n }\n\n // Public API\n getWorldState(): WorldState {\n return this.worldState;\n }\n\n getActiveEntities(): TrackedEntity[] {\n return this.worldState.activeEntities\n .map((id) => this.worldState.entities.get(id))\n .filter(Boolean) as TrackedEntity[];\n }\n\n getEntity(entityId: string): TrackedEntity | undefined {\n return this.worldState.entities.get(entityId);\n }\n\n getRecentlyLeft(): Array<{ entity: TrackedEntity; leftAt: number }> {\n return this.worldState.recentlyLeft\n .map((entry) => ({\n entity: this.worldState.entities.get(entry.entityId),\n leftAt: entry.leftAt,\n }))\n .filter((entry) => entry.entity) as Array<{ entity: TrackedEntity; leftAt: number }>;\n }\n\n // Name assignment\n assignNameToEntity(entityId: string, name: string): boolean {\n const entity = this.worldState.entities.get(entityId);\n if (entity) {\n entity.attributes.name = name;\n logger.info(`[EntityTracker] Assigned name \"${name}\" to entity ${entityId}`);\n return true;\n }\n return false;\n }\n\n // Get statistics\n getStatistics(): {\n totalEntities: number;\n activeEntities: number;\n recentlyLeft: number;\n people: number;\n objects: number;\n } {\n const entities = Array.from(this.worldState.entities.values());\n return {\n totalEntities: entities.length,\n activeEntities: this.worldState.activeEntities.length,\n recentlyLeft: this.worldState.recentlyLeft.length,\n people: entities.filter((e) => e.entityType === 'person').length,\n objects: entities.filter((e) => e.entityType === 'object').length,\n };\n }\n}\n"]}
@@ -0,0 +1,67 @@
1
+ export declare class VisionError extends Error {
2
+ readonly code: string;
3
+ readonly context?: Record<string, any>;
4
+ readonly recoverable: boolean;
5
+ constructor(message: string, code: string, recoverable?: boolean, context?: Record<string, any>);
6
+ }
7
+ export declare class CameraError extends VisionError {
8
+ constructor(message: string, context?: Record<string, any>);
9
+ }
10
+ export declare class ScreenCaptureError extends VisionError {
11
+ constructor(message: string, context?: Record<string, any>);
12
+ }
13
+ export declare class ModelInitializationError extends VisionError {
14
+ constructor(message: string, modelName: string, context?: Record<string, any>);
15
+ }
16
+ export declare class ProcessingError extends VisionError {
17
+ constructor(message: string, context?: Record<string, any>);
18
+ }
19
+ export declare class ConfigurationError extends VisionError {
20
+ constructor(message: string, context?: Record<string, any>);
21
+ }
22
+ export declare class APIError extends VisionError {
23
+ readonly statusCode?: number;
24
+ readonly endpoint?: string;
25
+ constructor(message: string, statusCode?: number, endpoint?: string, context?: Record<string, any>);
26
+ }
27
+ export interface RecoveryStrategy {
28
+ canRecover(error: VisionError): boolean;
29
+ recover(error: VisionError): Promise<void>;
30
+ }
31
+ export declare class ErrorRecoveryManager {
32
+ private strategies;
33
+ private errorCounts;
34
+ private readonly maxRetries;
35
+ constructor();
36
+ private registerDefaultStrategies;
37
+ registerStrategy(errorCode: string, strategy: RecoveryStrategy): void;
38
+ handleError(error: VisionError): Promise<boolean>;
39
+ resetErrorCount(errorCode: string): void;
40
+ resetAllCounts(): void;
41
+ }
42
+ export declare class CircuitBreaker {
43
+ private readonly threshold;
44
+ private readonly timeout;
45
+ private readonly name;
46
+ private failures;
47
+ private lastFailureTime;
48
+ private state;
49
+ constructor(threshold: number, timeout: number, // 1 minute
50
+ name: string);
51
+ execute<T>(operation: () => Promise<T>): Promise<T>;
52
+ private onSuccess;
53
+ private onFailure;
54
+ getState(): string;
55
+ reset(): void;
56
+ }
57
+ export declare class VisionErrorHandler {
58
+ private static instance;
59
+ private recoveryManager;
60
+ private circuitBreakers;
61
+ private constructor();
62
+ static getInstance(): VisionErrorHandler;
63
+ getCircuitBreaker(name: string, threshold?: number, timeout?: number): CircuitBreaker;
64
+ handle(error: any): Promise<boolean>;
65
+ resetCircuitBreaker(name: string): void;
66
+ resetAllCircuitBreakers(): void;
67
+ }