@elizaos/plugin-vision 2.0.0-alpha.8 → 2.0.0-beta.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.
package/dist/index.js.map CHANGED
@@ -1,32 +1,33 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/action.ts", "../src/types.ts", "../src/provider.ts", "../src/service.ts", "../src/audio-capture.ts", "../src/audio-capture-stream.ts", "../src/entity-tracker.ts", "../src/face-recognition.ts", "../src/florence2-model.ts", "../src/florence2-local.ts", "../src/ocr-service.ts", "../src/ocr-service-real.ts", "../src/screen-capture.ts", "../src/vision-models.ts", "../src/vision-worker-manager.ts", "../src/tests/e2e/screen-vision.ts", "../src/tests/e2e/vision-basic.ts", "../src/tests/e2e/vision-capture-log.ts", "../src/tests/e2e/vision-runtime.ts", "../src/tests/e2e/vision-worker-tests.ts", "../src/tests/test-pattern-generator.ts", "../src/tests/e2e/index.ts", "../src/index.ts"],
3
+ "sources": ["../src/index.ts", "../src/action.ts", "../src/types.ts", "../src/provider.ts", "../src/service.ts", "../src/audio-capture.ts", "../src/audio-capture-stream.ts", "../src/entity-tracker.ts", "../src/face-recognition.ts", "../src/florence2-model.ts", "../src/florence2-local.ts", "../src/ocr-service.ts", "../src/ocr-service-real.ts", "../src/screen-capture.ts", "../src/test-input.ts", "../src/vision-models.ts", "../src/vision-worker-manager.ts", "../src/tests/e2e/screen-vision.ts", "../src/tests/e2e/vision-basic.ts", "../src/tests/e2e/vision-capture-log.ts", "../src/tests/e2e/vision-runtime.ts", "../src/tests/e2e/vision-worker-tests.ts", "../src/tests/test-pattern-generator.ts", "../src/tests/e2e/index.ts"],
4
4
  "sourcesContent": [
5
- "import {\n type Action,\n type ActionExample,\n type ActionResult,\n ContentType,\n createUniqueUuid,\n type HandlerCallback,\n type IAgentRuntime,\n logger,\n type Media,\n type Memory,\n type State,\n} from \"@elizaos/core\";\nimport type { VisionService } from \"./service\";\nimport { VisionMode } from \"./types\";\n\nasync function saveExecutionRecord(\n runtime: IAgentRuntime,\n messageContext: Memory,\n thought: string,\n text: string,\n actions?: string[],\n attachments?: Media[]\n): Promise<void> {\n const memory: Memory = {\n id: createUniqueUuid(runtime, `vision-record-${Date.now()}`),\n content: {\n text,\n thought,\n actions: actions || [\"VISION_ANALYSIS\"],\n attachments,\n },\n entityId: createUniqueUuid(runtime, runtime.agentId),\n agentId: runtime.agentId,\n roomId: messageContext.roomId,\n worldId: messageContext.worldId,\n createdAt: Date.now(),\n };\n await runtime.createMemory(memory, \"messages\");\n}\n\nexport const describeSceneAction: Action = {\n name: \"DESCRIBE_SCENE\",\n similes: [\"ANALYZE_SCENE\", \"WHAT_DO_YOU_SEE\", \"VISION_CHECK\", \"LOOK_AROUND\"],\n description:\n \"Analyzes the current visual scene and provides a detailed description of what the agent sees through the camera. Returns scene analysis data including people count, objects, and camera info for action chaining.\",\n validate: async (runtime: any, message: any, state?: any, options?: any): Promise<boolean> => {\n \tconst __avTextRaw = typeof message?.content?.text === 'string' ? message.content.text : '';\n \tconst __avText = __avTextRaw.toLowerCase();\n \tconst __avVisionService = runtime?.getService?.(\"VISION\") as { isActive?: () => boolean } | null | undefined;\n \tconst __avLegacyContextOk = Boolean(__avVisionService && typeof __avVisionService.isActive === 'function' && __avVisionService.isActive());\n \tconst __avKeywords = ['describe', 'scene'];\n \tconst __avKeywordOk =\n \t\t__avKeywords.length > 0 &&\n \t\t(__avKeywords.some((kw) => kw.length > 0 && __avText.includes(kw)) || __avLegacyContextOk);\n \tconst __avRegex = new RegExp('\\\\b(?:describe|scene)\\\\b', 'i');\n \tconst __avRegexOk = __avRegex.test(__avText) || __avLegacyContextOk;\n \tconst __avSource = String(message?.content?.source ?? message?.source ?? '');\n \tconst __avExpectedSource = '';\n \tconst __avSourceOk = __avExpectedSource\n \t\t? __avSource === __avExpectedSource\n \t\t: Boolean(__avSource || state || runtime?.agentId || runtime?.getService);\n \tconst __avOptions = options && typeof options === 'object' ? options : {};\n \tconst __avInputOk =\n \t\t__avText.trim().length > 0 ||\n \t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n \t\tBoolean(message?.content && typeof message.content === 'object');\n\n \tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n \t\treturn false;\n \t}\n\n \tconst __avLegacyValidate = async (runtime: IAgentRuntime, _message: Memory, _state?: State): Promise<boolean> => {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n return !!visionService && visionService.isActive();\n };\n \ttry {\n \t\treturn Boolean(await (__avLegacyValidate as any)(runtime, message, state, options));\n \t} catch {\n \t\treturn false;\n \t}\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n _options?: Record<string, unknown>,\n callback?: HandlerCallback,\n _responses?: Memory[]\n ): Promise<ActionResult> => {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService || !visionService.isActive()) {\n const thought = \"Vision service is not available or no camera is connected.\";\n const text = \"I cannot see anything right now. No camera is available.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"DESCRIBE_SCENE\"]);\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"DESCRIBE_SCENE\"],\n });\n }\n return {\n success: false,\n text: \"Vision service unavailable - cannot analyze scene\",\n values: {\n success: false,\n visionAvailable: false,\n error: \"Vision service not available\",\n },\n data: {\n actionName: \"DESCRIBE_SCENE\",\n error: \"Vision service not available or no camera connected\",\n },\n };\n }\n\n try {\n const scene = await visionService.getSceneDescription();\n const cameraInfo = visionService.getCameraInfo();\n\n if (!scene) {\n const thought = \"Camera is connected but no scene has been analyzed yet.\";\n const text = `Camera \"${cameraInfo?.name}\" is connected, but I haven't analyzed any scenes yet. Please wait a moment.`;\n await saveExecutionRecord(runtime, message, thought, text, [\"DESCRIBE_SCENE\"]);\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"DESCRIBE_SCENE\"],\n });\n }\n return {\n success: false,\n text: \"Camera connected but no scene analyzed yet\",\n values: {\n success: false,\n visionAvailable: true,\n sceneAnalyzed: false,\n cameraName: cameraInfo?.name || undefined,\n },\n data: {\n actionName: \"DESCRIBE_SCENE\",\n cameraInfo: cameraInfo\n ? {\n id: cameraInfo.id,\n name: cameraInfo.name,\n connected: cameraInfo.connected,\n }\n : undefined,\n sceneStatus: \"not_analyzed\",\n },\n };\n }\n\n const peopleCount = scene.people.length;\n const objectCount = scene.objects.length;\n const timestamp = new Date(scene.timestamp).toLocaleString();\n\n let description = `Looking through ${cameraInfo?.name || \"the camera\"}, `;\n description += scene.description;\n\n if (peopleCount > 0) {\n description += `\\n\\nI can see ${peopleCount} ${peopleCount === 1 ? \"person\" : \"people\"}`;\n const facingData = scene.people.reduce(\n (acc, person) => {\n if (person.facing && person.facing !== \"unknown\") {\n acc[person.facing] = (acc[person.facing] || 0) + 1;\n }\n return acc;\n },\n {} as Record<string, number>\n );\n\n if (Object.keys(facingData).length > 0) {\n const facingDescriptions = Object.entries(facingData).map(\n ([direction, count]) => `${count} facing ${direction}`\n );\n description += ` (${facingDescriptions.join(\", \")})`;\n }\n description += \".\";\n }\n\n if (objectCount > 0) {\n const objectTypes = scene.objects.reduce(\n (acc, obj) => {\n acc[obj.type] = (acc[obj.type] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>\n );\n\n const objectDescriptions = Object.entries(objectTypes).map(\n ([type, count]) => `${count} ${type}${count > 1 ? \"s\" : \"\"}`\n );\n description += `\\n\\nObjects detected: ${objectDescriptions.join(\", \")}.`;\n }\n\n if (scene.sceneChanged && scene.changePercentage) {\n description += `\\n\\n(Scene changed by ${scene.changePercentage.toFixed(1)}% since last analysis)`;\n }\n\n const thought = `Analyzed the visual scene at ${timestamp}.`;\n const text = description;\n\n await saveExecutionRecord(runtime, message, thought, text, [\"DESCRIBE_SCENE\"]);\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"DESCRIBE_SCENE\"],\n });\n }\n\n return {\n success: true,\n text: description,\n values: {\n success: true,\n visionAvailable: true,\n sceneAnalyzed: true,\n peopleCount,\n objectCount,\n cameraName: cameraInfo?.name || undefined,\n sceneChanged: scene.sceneChanged,\n changePercentage: scene.changePercentage,\n },\n data: {\n actionName: \"DESCRIBE_SCENE\",\n sceneTimestamp: scene.timestamp,\n sceneDescription: scene.description,\n sceneChanged: scene.sceneChanged,\n changePercentage: scene.changePercentage,\n audioTranscription: scene.audioTranscription || undefined,\n objectCount: scene.objects.length,\n peopleCount: scene.people.length,\n cameraInfo: cameraInfo\n ? {\n id: cameraInfo.id,\n name: cameraInfo.name,\n connected: cameraInfo.connected,\n }\n : undefined,\n timestamp,\n description,\n },\n };\n } catch (error: unknown) {\n logger.error(\n \"[describeSceneAction] Error analyzing scene:\",\n error instanceof Error ? error.message : String(error)\n );\n const thought = \"An error occurred while trying to analyze the visual scene.\";\n const text = `Error analyzing scene: ${error instanceof Error ? error.message : String(error)}`;\n await saveExecutionRecord(runtime, message, thought, text, [\"DESCRIBE_SCENE\"]);\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"DESCRIBE_SCENE\"],\n });\n }\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n text: \"Error analyzing scene\",\n values: {\n success: false,\n visionAvailable: true,\n error: true,\n errorMessage,\n },\n data: {\n actionName: \"DESCRIBE_SCENE\",\n error: errorMessage,\n errorType: \"analysis_error\",\n },\n };\n }\n },\n examples: [\n [\n { name: \"{{user}}\", content: { text: \"what do you see?\" } },\n {\n name: \"{{agent}}\",\n content: {\n actions: [\"DESCRIBE_SCENE\"],\n thought: \"The user wants to know what I can see through my camera.\",\n text: \"I see a room with a desk and computer setup. There are 2 people, one is sitting and one is standing.\",\n },\n },\n ],\n [\n { name: \"{{user}}\", content: { text: \"describe the scene and then take a photo\" } },\n {\n name: \"{{agent}}\",\n content: {\n actions: [\"DESCRIBE_SCENE\", \"CAPTURE_IMAGE\"],\n thought: \"I should first analyze the scene, then capture an image for the user.\",\n text: \"I can see 3 people in an office setting. Let me capture this scene for you.\",\n },\n },\n ],\n ] as ActionExample[][],\n};\n\nexport const captureImageAction: Action = {\n name: \"CAPTURE_IMAGE\",\n similes: [\"TAKE_PHOTO\", \"SCREENSHOT\", \"CAPTURE_FRAME\", \"TAKE_PICTURE\"],\n description:\n \"Captures the current frame from the camera and saves it as an image attachment. Returns image data with camera info and timestamp for action chaining. Can be combined with DESCRIBE_SCENE for analysis or NAME_ENTITY for identification workflows.\",\n validate: async (runtime: any, message: any, state?: any, options?: any): Promise<boolean> => {\n \tconst __avTextRaw = typeof message?.content?.text === 'string' ? message.content.text : '';\n \tconst __avText = __avTextRaw.toLowerCase();\n \tconst __avVisionService = runtime?.getService?.(\"VISION\") as { isActive?: () => boolean } | null | undefined;\n \tconst __avLegacyContextOk = Boolean(__avVisionService && typeof __avVisionService.isActive === 'function' && __avVisionService.isActive());\n \tconst __avKeywords = ['capture', 'image'];\n \tconst __avKeywordOk =\n \t\t__avKeywords.length > 0 &&\n \t\t(__avKeywords.some((kw) => kw.length > 0 && __avText.includes(kw)) || __avLegacyContextOk);\n \tconst __avRegex = new RegExp('\\\\b(?:capture|image)\\\\b', 'i');\n \tconst __avRegexOk = __avRegex.test(__avText) || __avLegacyContextOk;\n \tconst __avSource = String(message?.content?.source ?? message?.source ?? '');\n \tconst __avExpectedSource = '';\n \tconst __avSourceOk = __avExpectedSource\n \t\t? __avSource === __avExpectedSource\n \t\t: Boolean(__avSource || state || runtime?.agentId || runtime?.getService);\n \tconst __avOptions = options && typeof options === 'object' ? options : {};\n \tconst __avInputOk =\n \t\t__avText.trim().length > 0 ||\n \t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n \t\tBoolean(message?.content && typeof message.content === 'object');\n\n \tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n \t\treturn false;\n \t}\n\n \tconst __avLegacyValidate = async (runtime: IAgentRuntime, _message: Memory, _state?: State): Promise<boolean> => {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n return !!visionService && visionService.isActive();\n };\n \ttry {\n \t\treturn Boolean(await (__avLegacyValidate as any)(runtime, message, state, options));\n \t} catch {\n \t\treturn false;\n \t}\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n _options?: Record<string, unknown>,\n callback?: HandlerCallback,\n _responses?: Memory[]\n ): Promise<ActionResult> => {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService || !visionService.isActive()) {\n const thought = \"Vision service is not available or no camera is connected.\";\n const text = \"I cannot capture an image right now. No camera is available.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"CAPTURE_IMAGE\"]);\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"CAPTURE_IMAGE\"],\n });\n }\n return {\n success: false,\n text: \"Vision service unavailable - cannot capture image\",\n values: {\n success: false,\n visionAvailable: false,\n error: \"Vision service not available\",\n },\n data: {\n actionName: \"CAPTURE_IMAGE\",\n error: \"Vision service not available or no camera connected\",\n },\n };\n }\n\n try {\n const imageBuffer = await visionService.captureImage();\n const cameraInfo = visionService.getCameraInfo();\n\n if (!imageBuffer) {\n const thought = \"Failed to capture image from camera.\";\n const text = \"I could not capture an image from the camera. Please try again.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"CAPTURE_IMAGE\"]);\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"CAPTURE_IMAGE\"],\n });\n }\n return {\n success: false,\n text: \"Failed to capture image from camera\",\n values: {\n success: false,\n visionAvailable: true,\n captureSuccess: false,\n },\n data: {\n actionName: \"CAPTURE_IMAGE\",\n error: \"Camera capture failed\",\n cameraInfo: cameraInfo\n ? {\n id: cameraInfo.id,\n name: cameraInfo.name,\n connected: cameraInfo.connected,\n }\n : undefined,\n },\n };\n }\n\n const attachmentId = createUniqueUuid(runtime, `capture-${Date.now()}`);\n const timestamp = new Date().toISOString();\n\n const imageAttachment: Media = {\n id: attachmentId,\n title: `Camera Capture - ${timestamp}`,\n contentType: ContentType.IMAGE,\n source: `camera:${cameraInfo?.name || \"unknown\"}`,\n url: `data:image/jpeg;base64,${imageBuffer.toString(\"base64\")}`,\n };\n\n const thought = `Captured an image from camera \"${cameraInfo?.name}\".`;\n const text = `I've captured an image from the camera at ${timestamp}.`;\n\n await saveExecutionRecord(\n runtime,\n message,\n thought,\n text,\n [\"CAPTURE_IMAGE\"],\n [imageAttachment]\n );\n\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"CAPTURE_IMAGE\"],\n attachments: [imageAttachment],\n });\n }\n\n return {\n success: true,\n text: `I've captured an image from the camera at ${timestamp}.`,\n values: {\n success: true,\n visionAvailable: true,\n captureSuccess: true,\n cameraName: cameraInfo?.name || undefined,\n timestamp,\n },\n data: {\n actionName: \"CAPTURE_IMAGE\",\n imageAttachment: {\n id: imageAttachment.id,\n title: imageAttachment.title,\n contentType: imageAttachment.contentType,\n source: imageAttachment.source,\n url: imageAttachment.url,\n },\n cameraInfo: cameraInfo\n ? {\n id: cameraInfo.id,\n name: cameraInfo.name,\n connected: cameraInfo.connected,\n }\n : undefined,\n timestamp,\n },\n };\n } catch (error) {\n logger.error(\"[captureImageAction] Error capturing image:\", error);\n const thought = \"An error occurred while trying to capture an image.\";\n const errorMessage = error instanceof Error ? error.message : String(error);\n const text = `Error capturing image: ${errorMessage}`;\n await saveExecutionRecord(runtime, message, thought, text, [\"CAPTURE_IMAGE\"]);\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"CAPTURE_IMAGE\"],\n });\n }\n\n return {\n success: false,\n text: \"Error capturing image\",\n values: {\n success: false,\n visionAvailable: true,\n error: true,\n errorMessage,\n },\n data: {\n actionName: \"CAPTURE_IMAGE\",\n error: errorMessage,\n errorType: \"capture_error\",\n },\n };\n }\n },\n examples: [\n // Multi-action: Describe scene then capture image\n [\n { name: \"{{user}}\", content: { text: \"describe what you see and take a photo\" } },\n {\n name: \"{{agent}}\",\n content: {\n actions: [\"DESCRIBE_SCENE\", \"CAPTURE_IMAGE\"],\n thought: \"User wants scene analysis followed by image capture.\",\n text: \"I can see 3 people in an office setting. Let me capture this scene for you.\",\n },\n },\n ],\n [\n { name: \"{{user}}\", content: { text: \"take a photo\" } },\n {\n name: \"{{agent}}\",\n content: {\n actions: [\"CAPTURE_IMAGE\"],\n thought: \"The user wants me to capture an image from the camera.\",\n text: \"I've captured an image from the camera.\",\n },\n },\n ],\n [\n { name: \"{{user}}\", content: { text: \"capture the current scene\" } },\n {\n name: \"{{agent}}\",\n content: {\n actions: [\"CAPTURE_IMAGE\"],\n },\n },\n ],\n ] as ActionExample[][],\n};\n\nexport const setVisionModeAction: Action = {\n name: \"SET_VISION_MODE\",\n description: \"Set the vision mode to OFF, CAMERA, SCREEN, or BOTH\",\n similes: [\n \"change vision to {mode}\",\n \"set vision mode {mode}\",\n \"switch to {mode} vision\",\n \"turn vision {mode}\",\n \"use {mode} vision\",\n \"enable {mode} vision\",\n \"disable vision\",\n ],\n validate: async (runtime: any, message: any, state?: any, options?: any): Promise<boolean> => {\n \tconst __avTextRaw = typeof message?.content?.text === 'string' ? message.content.text : '';\n \tconst __avText = __avTextRaw.toLowerCase();\n \tconst __avLegacyContextOk = Boolean(runtime?.getService?.(\"VISION\"));\n \tconst __avKeywords = ['set', 'vision', 'mode'];\n \tconst __avKeywordOk =\n \t\t__avKeywords.length > 0 &&\n \t\t(__avKeywords.some((kw) => kw.length > 0 && __avText.includes(kw)) || __avLegacyContextOk);\n \tconst __avRegex = new RegExp('\\\\b(?:set|vision|mode)\\\\b', 'i');\n \tconst __avRegexOk = __avRegex.test(__avText) || __avLegacyContextOk;\n \tconst __avSource = String(message?.content?.source ?? message?.source ?? '');\n \tconst __avExpectedSource = '';\n \tconst __avSourceOk = __avExpectedSource\n \t\t? __avSource === __avExpectedSource\n \t\t: Boolean(__avSource || state || runtime?.agentId || runtime?.getService);\n \tconst __avOptions = options && typeof options === 'object' ? options : {};\n \tconst __avInputOk =\n \t\t__avText.trim().length > 0 ||\n \t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n \t\tBoolean(message?.content && typeof message.content === 'object');\n\n \tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n \t\treturn false;\n \t}\n\n \tconst __avLegacyValidate = async (runtime: IAgentRuntime, _message: Memory, _state?: State): Promise<boolean> => {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n return visionService !== null;\n };\n \ttry {\n \t\treturn Boolean(await (__avLegacyValidate as any)(runtime, message, state, options));\n \t} catch {\n \t\treturn false;\n \t}\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n _options?: Record<string, unknown>,\n callback?: HandlerCallback,\n _responses?: Memory[]\n ): Promise<ActionResult> => {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService) {\n const thought = \"Vision service is not available.\";\n const text = \"I cannot change vision mode because the vision service is not available.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"SET_VISION_MODE\"]);\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"SET_VISION_MODE\"],\n });\n }\n return {\n success: false,\n text,\n };\n }\n\n try {\n const messageText = message.content.text?.toLowerCase() || \"\";\n let newMode: VisionMode | null = null;\n\n if (messageText.includes(\"off\") || messageText.includes(\"disable\")) {\n newMode = VisionMode.OFF;\n } else if (messageText.includes(\"both\")) {\n newMode = VisionMode.BOTH;\n } else if (messageText.includes(\"screen\")) {\n newMode = VisionMode.SCREEN;\n } else if (messageText.includes(\"camera\")) {\n newMode = VisionMode.CAMERA;\n }\n\n if (!newMode) {\n const thought = \"Could not determine the desired vision mode from the message.\";\n const text = \"Please specify the vision mode: OFF, CAMERA, SCREEN, or BOTH.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"SET_VISION_MODE\"]);\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"SET_VISION_MODE\"],\n });\n }\n return {\n success: false,\n text,\n };\n }\n\n const currentMode = visionService.getVisionMode();\n await visionService.setVisionMode(newMode);\n\n const thought = `Changed vision mode from ${currentMode} to ${newMode}.`;\n let text = \"\";\n\n switch (newMode) {\n case VisionMode.OFF:\n text = \"Vision has been disabled. I will no longer process visual input.\";\n break;\n case VisionMode.CAMERA:\n text = \"Vision mode set to CAMERA only. I will process input from the camera.\";\n break;\n case VisionMode.SCREEN:\n text = \"Vision mode set to SCREEN only. I will analyze what's on your screen.\";\n break;\n case VisionMode.BOTH:\n text = \"Vision mode set to BOTH. I will process input from both camera and screen.\";\n break;\n }\n\n await saveExecutionRecord(runtime, message, thought, text, [\"SET_VISION_MODE\"]);\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"SET_VISION_MODE\"],\n });\n }\n return {\n success: true,\n text,\n values: {\n visionMode: newMode,\n },\n };\n } catch (error) {\n logger.error(\"[setVisionModeAction] Error changing vision mode:\", error);\n const thought = \"An error occurred while trying to change the vision mode.\";\n const errorMessage = error instanceof Error ? error.message : String(error);\n const text = `Error changing vision mode: ${errorMessage}`;\n await saveExecutionRecord(runtime, message, thought, text, [\"SET_VISION_MODE\"]);\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"SET_VISION_MODE\"],\n });\n }\n return {\n success: false,\n text,\n error: errorMessage,\n };\n }\n },\n examples: [\n [\n { name: \"user\", content: { text: \"set vision mode to screen\" } },\n {\n name: \"agent\",\n content: {\n actions: [\"SET_VISION_MODE\"],\n thought: \"The user wants to switch to screen vision mode.\",\n text: \"Vision mode set to SCREEN only. I will analyze what's on your screen.\",\n },\n },\n ],\n [\n { name: \"user\", content: { text: \"enable both camera and screen vision\" } },\n {\n name: \"agent\",\n content: {\n actions: [\"SET_VISION_MODE\"],\n thought: \"The user wants to enable both vision inputs.\",\n text: \"Vision mode set to BOTH. I will process input from both camera and screen.\",\n },\n },\n ],\n [\n { name: \"user\", content: { text: \"turn off vision\" } },\n {\n name: \"agent\",\n content: {\n actions: [\"SET_VISION_MODE\"],\n thought: \"The user wants to disable vision.\",\n text: \"Vision has been disabled. I will no longer process visual input.\",\n },\n },\n ],\n ],\n};\n\nexport const nameEntityAction: Action = {\n name: \"NAME_ENTITY\",\n description: \"Assign a name to a person or object currently visible in the camera view\",\n similes: [\n \"call the person {name}\",\n \"the person in front is {name}\",\n \"name the person {name}\",\n \"that person is {name}\",\n \"the object is a {name}\",\n \"call that {name}\",\n ],\n examples: [\n [\n {\n name: \"user\",\n content: {\n text: \"The person wearing the blue shirt is named Alice\",\n },\n },\n {\n name: \"agent\",\n content: {\n text: \"I've identified the person in the blue shirt as Alice. I'll remember them for future interactions.\",\n actions: [\"NAME_ENTITY\"],\n },\n },\n ],\n [\n {\n name: \"user\",\n content: {\n text: \"Call the person on the left Bob\",\n },\n },\n {\n name: \"agent\",\n content: {\n text: \"I've named the person on the left as Bob. Their face profile has been updated.\",\n actions: [\"NAME_ENTITY\"],\n },\n },\n ],\n ],\n\n validate: async (runtime: any, message: any, state?: any, options?: any): Promise<boolean> => {\n \tconst __avTextRaw = typeof message?.content?.text === 'string' ? message.content.text : '';\n \tconst __avText = __avTextRaw.toLowerCase();\n \tconst __avVisionService = runtime?.getService?.(\"VISION\") as { isActive?: () => boolean } | null | undefined;\n \tconst __avLegacyContextOk = Boolean(__avVisionService && typeof __avVisionService.isActive === 'function' && __avVisionService.isActive());\n \tconst __avKeywords = ['name', 'entity'];\n \tconst __avKeywordOk =\n \t\t__avKeywords.length > 0 &&\n \t\t(__avKeywords.some((kw) => kw.length > 0 && __avText.includes(kw)) || __avLegacyContextOk);\n \tconst __avRegex = new RegExp('\\\\b(?:name|entity)\\\\b', 'i');\n \tconst __avRegexOk = __avRegex.test(__avText) || __avLegacyContextOk;\n \tconst __avSource = String(message?.content?.source ?? message?.source ?? '');\n \tconst __avExpectedSource = '';\n \tconst __avSourceOk = __avExpectedSource\n \t\t? __avSource === __avExpectedSource\n \t\t: Boolean(__avSource || state || runtime?.agentId || runtime?.getService);\n \tconst __avOptions = options && typeof options === 'object' ? options : {};\n \tconst __avInputOk =\n \t\t__avText.trim().length > 0 ||\n \t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n \t\tBoolean(message?.content && typeof message.content === 'object');\n\n \tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n \t\treturn false;\n \t}\n\n \tconst __avLegacyValidate = async (runtime: IAgentRuntime, _message: Memory, _state?: State): Promise<boolean> => {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n return visionService?.isActive() || false;\n };\n \ttry {\n \t\treturn Boolean(await (__avLegacyValidate as any)(runtime, message, state, options));\n \t} catch {\n \t\treturn false;\n \t}\n },\n\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n _options?: Record<string, unknown>,\n callback?: HandlerCallback\n ): Promise<ActionResult> => {\n try {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService) {\n const thought = \"Vision service is not available.\";\n const text = \"I cannot name entities because the vision service is not available.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"NAME_ENTITY\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"NAME_ENTITY\"] });\n }\n return {\n success: false,\n text,\n };\n }\n\n const scene = await visionService.getSceneDescription();\n\n if (!scene || scene.people.length === 0) {\n const thought = \"No people visible to name.\";\n const text = \"I don't see any people in the current scene to name.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"NAME_ENTITY\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"NAME_ENTITY\"] });\n }\n return {\n success: false,\n text,\n };\n }\n\n const text = message.content.text?.toLowerCase() || \"\";\n const nameMatch = text.match(/(?:named?|call(?:ed)?|is)\\s+(\\w+)/i);\n\n if (!nameMatch) {\n const thought = \"Could not extract name from message.\";\n const text =\n 'I couldn\\'t understand what name to assign. Please say something like \"The person is named Alice\".';\n await saveExecutionRecord(runtime, message, thought, text, [\"NAME_ENTITY\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"NAME_ENTITY\"] });\n }\n return {\n success: false,\n text,\n };\n }\n\n const name = nameMatch[1];\n const _worldId = message.worldId || \"default-world\";\n const entityTracker = visionService.getEntityTracker();\n\n // Update entities\n await entityTracker.updateEntities(scene.objects, scene.people, undefined, runtime);\n const activeEntities = entityTracker.getActiveEntities();\n const people = activeEntities.filter((e) => e.entityType === \"person\");\n\n if (people.length === 0) {\n const thought = \"No tracked people found.\";\n const text =\n \"I can see someone but haven't established tracking yet. Please try again in a moment.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"NAME_ENTITY\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"NAME_ENTITY\"] });\n }\n return {\n success: false,\n text,\n };\n }\n\n // For now, assign to the most prominent person (largest bounding box)\n let targetPerson = people[0];\n if (people.length > 1) {\n targetPerson = people.reduce((prev, curr) => {\n const prevArea = prev.lastPosition.width * prev.lastPosition.height;\n const currArea = curr.lastPosition.width * curr.lastPosition.height;\n return currArea > prevArea ? curr : prev;\n });\n }\n\n const success = entityTracker.assignNameToEntity(targetPerson.id, name);\n\n if (success) {\n const thought = `Named entity \"${name}\" and associated with person in scene.`;\n const text = `I've identified the person as ${name}. I'll remember them for future interactions.`;\n\n await saveExecutionRecord(runtime, message, thought, text, [\"NAME_ENTITY\"], undefined);\n\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"NAME_ENTITY\"],\n data: { entityId: targetPerson.id, name },\n });\n }\n\n logger.info(`[NameEntityAction] Assigned name \"${name}\" to entity ${targetPerson.id}`);\n return {\n success: true,\n text,\n values: {\n entityId: targetPerson.id,\n name,\n },\n };\n } else {\n const thought = \"Failed to assign name to entity.\";\n const text = \"There was an error assigning the name. Please try again.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"NAME_ENTITY\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"NAME_ENTITY\"] });\n }\n return {\n success: false,\n text,\n };\n }\n } catch (error) {\n logger.error(\"[NameEntityAction] Error:\", error);\n const thought = \"Failed to name entity.\";\n const text = `Sorry, I couldn't name the entity: ${error instanceof Error ? error.message : \"Unknown error\"}`;\n await saveExecutionRecord(runtime, message, thought, text, [\"NAME_ENTITY\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"NAME_ENTITY\"] });\n }\n return {\n success: false,\n text,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n },\n};\n\nexport const identifyPersonAction: Action = {\n name: \"IDENTIFY_PERSON\",\n description: \"Identify a person in view if they have been seen before\",\n similes: [\n \"who is that\",\n \"who is the person\",\n \"identify the person\",\n \"do you recognize them\",\n \"have you seen them before\",\n ],\n examples: [\n [\n {\n name: \"user\",\n content: {\n text: \"Who is the person in front of you?\",\n },\n },\n {\n name: \"agent\",\n content: {\n text: \"That's Alice. I last saw her about 5 minutes ago. She's been here for the past 20 minutes.\",\n actions: [\"IDENTIFY_PERSON\"],\n },\n },\n ],\n ],\n\n validate: async (runtime: any, message: any, state?: any, options?: any): Promise<boolean> => {\n \tconst __avTextRaw = typeof message?.content?.text === 'string' ? message.content.text : '';\n \tconst __avText = __avTextRaw.toLowerCase();\n \tconst __avVisionService = runtime?.getService?.(\"VISION\") as { isActive?: () => boolean } | null | undefined;\n \tconst __avLegacyContextOk = Boolean(__avVisionService && typeof __avVisionService.isActive === 'function' && __avVisionService.isActive());\n \tconst __avKeywords = ['identify', 'person'];\n \tconst __avKeywordOk =\n \t\t__avKeywords.length > 0 &&\n \t\t(__avKeywords.some((kw) => kw.length > 0 && __avText.includes(kw)) || __avLegacyContextOk);\n \tconst __avRegex = new RegExp('\\\\b(?:identify|person)\\\\b', 'i');\n \tconst __avRegexOk = __avRegex.test(__avText) || __avLegacyContextOk;\n \tconst __avSource = String(message?.content?.source ?? message?.source ?? '');\n \tconst __avExpectedSource = '';\n \tconst __avSourceOk = __avExpectedSource\n \t\t? __avSource === __avExpectedSource\n \t\t: Boolean(__avSource || state || runtime?.agentId || runtime?.getService);\n \tconst __avOptions = options && typeof options === 'object' ? options : {};\n \tconst __avInputOk =\n \t\t__avText.trim().length > 0 ||\n \t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n \t\tBoolean(message?.content && typeof message.content === 'object');\n\n \tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n \t\treturn false;\n \t}\n\n \tconst __avLegacyValidate = async (runtime: IAgentRuntime, _message: Memory, _state?: State): Promise<boolean> => {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n return visionService?.isActive() || false;\n };\n \ttry {\n \t\treturn Boolean(await (__avLegacyValidate as any)(runtime, message, state, options));\n \t} catch {\n \t\treturn false;\n \t}\n },\n\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n _options?: Record<string, unknown>,\n callback?: HandlerCallback\n ): Promise<ActionResult> => {\n try {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService) {\n const thought = \"Vision service is not available.\";\n const text = \"I cannot identify people because the vision service is not available.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"IDENTIFY_PERSON\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"IDENTIFY_PERSON\"] });\n }\n return {\n success: false,\n text,\n };\n }\n\n const scene = await visionService.getSceneDescription();\n\n if (!scene || scene.people.length === 0) {\n const thought = \"No people visible to identify.\";\n const text = \"I don't see any people in the current scene.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"IDENTIFY_PERSON\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"IDENTIFY_PERSON\"] });\n }\n return {\n success: false,\n text,\n };\n }\n\n // Get entity tracker\n const _worldId = message.worldId || \"default-world\";\n const entityTracker = visionService.getEntityTracker();\n\n // Update entities\n await entityTracker.updateEntities(scene.objects, scene.people, undefined, runtime);\n const activeEntities = entityTracker.getActiveEntities();\n const people = activeEntities.filter((e) => e.entityType === \"person\");\n\n if (people.length === 0) {\n const thought = \"No tracked people found.\";\n const text = \"I can see someone but I'm still processing their identity.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"IDENTIFY_PERSON\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"IDENTIFY_PERSON\"] });\n }\n return {\n success: false,\n text,\n };\n }\n\n const _responseText = \"\";\n let recognizedCount = 0;\n let unknownCount = 0;\n const identifications: string[] = [];\n\n for (const person of people) {\n const name = person.attributes.name;\n const duration = Date.now() - person.firstSeen;\n const durationStr =\n duration < 60000\n ? `${Math.round(duration / 1000)} seconds`\n : `${Math.round(duration / 60000)} minutes`;\n\n if (name) {\n recognizedCount++;\n const personInfo = `I can see ${name}. They've been here for ${durationStr}.`;\n identifications.push(personInfo);\n\n // Add more context if available\n if (person.appearances.length > 5) {\n identifications.push(\"I've been tracking them consistently.\");\n }\n } else {\n unknownCount++;\n const personInfo = `I see an unidentified person who has been here for ${durationStr}.`;\n identifications.push(personInfo);\n\n if (person.attributes.faceId) {\n identifications.push(\n \"I've captured their face profile but they haven't been named yet.\"\n );\n }\n }\n }\n\n const recentlyLeft = entityTracker.getRecentlyLeft();\n if (recentlyLeft.length > 0) {\n identifications.push(\"\\nRecently departed:\");\n for (const { entity, leftAt } of recentlyLeft) {\n if (entity.entityType === \"person\" && entity.attributes.name) {\n const timeAgo = Date.now() - leftAt;\n const timeStr =\n timeAgo < 60000\n ? `${Math.round(timeAgo / 1000)} seconds ago`\n : `${Math.round(timeAgo / 60000)} minutes ago`;\n identifications.push(`${entity.attributes.name} left ${timeStr}.`);\n }\n }\n }\n\n const thought = `Identified ${recognizedCount} known people and ${unknownCount} unknown people.`;\n const text = identifications.join(\" \");\n\n await saveExecutionRecord(runtime, message, thought, text, [\"IDENTIFY_PERSON\"]);\n\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"IDENTIFY_PERSON\"],\n data: {\n identifications: people.map((p) => ({\n id: p.id,\n entityType: p.entityType,\n name: p.attributes.name || undefined,\n })),\n },\n });\n }\n return {\n success: true,\n text,\n values: {\n recognizedCount,\n unknownCount,\n },\n };\n } catch (error) {\n logger.error(\"[identifyPersonAction] Error:\", error);\n const thought = \"Failed to identify people.\";\n const text = `Sorry, I couldn't identify people: ${error instanceof Error ? error.message : \"Unknown error\"}`;\n await saveExecutionRecord(runtime, message, thought, text, [\"IDENTIFY_PERSON\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"IDENTIFY_PERSON\"] });\n }\n return {\n success: false,\n text,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n },\n};\n\nexport const trackEntityAction: Action = {\n name: \"TRACK_ENTITY\",\n description: \"Start tracking a specific person or object in view\",\n similes: [\n \"track the {description}\",\n \"follow the {description}\",\n \"keep an eye on the {description}\",\n \"watch the {description}\",\n ],\n examples: [\n [\n {\n name: \"user\",\n content: {\n text: \"Track the person wearing the red shirt\",\n },\n },\n {\n name: \"agent\",\n content: {\n text: \"I'm now tracking the person in the red shirt. I'll notify you of any significant movements or if they leave the scene.\",\n actions: [\"TRACK_ENTITY\"],\n },\n },\n ],\n ],\n\n validate: async (runtime: any, message: any, state?: any, options?: any): Promise<boolean> => {\n \tconst __avTextRaw = typeof message?.content?.text === 'string' ? message.content.text : '';\n \tconst __avText = __avTextRaw.toLowerCase();\n \tconst __avVisionService = runtime?.getService?.(\"VISION\") as { isActive?: () => boolean } | null | undefined;\n \tconst __avLegacyContextOk = Boolean(__avVisionService && typeof __avVisionService.isActive === 'function' && __avVisionService.isActive());\n \tconst __avKeywords = ['track', 'entity'];\n \tconst __avKeywordOk =\n \t\t__avKeywords.length > 0 &&\n \t\t(__avKeywords.some((kw) => kw.length > 0 && __avText.includes(kw)) || __avLegacyContextOk);\n \tconst __avRegex = new RegExp('\\\\b(?:track|entity)\\\\b', 'i');\n \tconst __avRegexOk = __avRegex.test(__avText) || __avLegacyContextOk;\n \tconst __avSource = String(message?.content?.source ?? message?.source ?? '');\n \tconst __avExpectedSource = '';\n \tconst __avSourceOk = __avExpectedSource\n \t\t? __avSource === __avExpectedSource\n \t\t: Boolean(__avSource || state || runtime?.agentId || runtime?.getService);\n \tconst __avOptions = options && typeof options === 'object' ? options : {};\n \tconst __avInputOk =\n \t\t__avText.trim().length > 0 ||\n \t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n \t\tBoolean(message?.content && typeof message.content === 'object');\n\n \tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n \t\treturn false;\n \t}\n\n \tconst __avLegacyValidate = async (runtime: IAgentRuntime, _message: Memory, _state?: State): Promise<boolean> => {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n return visionService?.isActive() || false;\n };\n \ttry {\n \t\treturn Boolean(await (__avLegacyValidate as any)(runtime, message, state, options));\n \t} catch {\n \t\treturn false;\n \t}\n },\n\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n _options?: Record<string, unknown>,\n callback?: HandlerCallback\n ): Promise<ActionResult> => {\n try {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService) {\n const thought = \"Vision service is not available.\";\n const text = \"I cannot track entities because the vision service is not available.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"TRACK_ENTITY\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"TRACK_ENTITY\"] });\n }\n return {\n success: false,\n text,\n };\n }\n\n const scene = await visionService.getSceneDescription();\n\n if (!scene) {\n const thought = \"No scene available for tracking.\";\n const text = \"I need a moment to process the visual scene before I can track entities.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"TRACK_ENTITY\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"TRACK_ENTITY\"] });\n }\n return {\n success: false,\n text,\n };\n }\n\n const _text = message.content.text?.toLowerCase() || \"\";\n const _worldId = message.worldId || \"default-world\";\n const entityTracker = visionService.getEntityTracker();\n await entityTracker.updateEntities(scene.objects, scene.people, undefined, runtime);\n const stats = entityTracker.getStatistics();\n\n const thought = `Tracking ${stats.activeEntities} entities in the scene.`;\n const summary = [\n `I'm now tracking ${stats.activeEntities} entities in the scene`,\n `(${stats.people} people, ${stats.objects} objects).`,\n \"The visual tracking system will maintain persistent IDs for all entities\",\n \"and notify you of significant changes.\",\n ];\n const responseText = summary.join(\" \");\n\n await saveExecutionRecord(runtime, message, thought, responseText, [\"TRACK_ENTITY\"]);\n\n if (callback) {\n await callback({\n thought,\n text: responseText,\n actions: [\"TRACK_ENTITY\"],\n data: { entities: stats.activeEntities },\n });\n }\n\n logger.info(`[TrackEntityAction] Tracking ${stats.activeEntities} entities`);\n return {\n success: true,\n text: responseText,\n values: {\n activeEntities: stats.activeEntities,\n people: stats.people,\n objects: stats.objects,\n },\n };\n } catch (error) {\n logger.error(\"[trackEntityAction] Error:\", error);\n const thought = \"Failed to track entities.\";\n const text = `Sorry, I couldn't track entities: ${error instanceof Error ? error.message : \"Unknown error\"}`;\n await saveExecutionRecord(runtime, message, thought, text, [\"TRACK_ENTITY\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"TRACK_ENTITY\"] });\n }\n return {\n success: false,\n text,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n },\n};\n",
6
- "export const VisionServiceType = {\n VISION: \"VISION\" as const,\n};\n\ndeclare module \"@elizaos/core\" {\n interface ServiceTypeRegistry {\n VISION: \"VISION\";\n }\n}\n\nexport interface CameraInfo {\n id: string;\n name: string;\n connected: boolean;\n}\n\nexport interface SceneDescription {\n timestamp: number;\n description: string;\n objects: DetectedObject[];\n people: PersonInfo[];\n sceneChanged: boolean;\n changePercentage: number;\n audioTranscription?: string;\n}\n\nexport interface DetectedObject {\n id: string;\n type: string;\n confidence: number;\n boundingBox: BoundingBox;\n}\n\nexport interface PersonInfo {\n id: string;\n pose: \"sitting\" | \"standing\" | \"lying\" | \"unknown\";\n facing: \"camera\" | \"away\" | \"left\" | \"right\" | \"unknown\";\n confidence: number;\n boundingBox: BoundingBox;\n keypoints?: Array<{\n part: string;\n position: { x: number; y: number };\n score: number;\n }>;\n}\n\nexport interface BoundingBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface VisionFrame {\n timestamp: number;\n width: number;\n height: number;\n data: Buffer;\n format: \"rgb\" | \"rgba\" | \"jpeg\" | \"png\";\n}\n\nexport enum VisionMode {\n OFF = \"OFF\",\n CAMERA = \"CAMERA\",\n SCREEN = \"SCREEN\",\n BOTH = \"BOTH\",\n}\n\n// Screen capture types\nexport interface ScreenCapture {\n timestamp: number;\n width: number;\n height: number;\n data: Buffer;\n tiles: ScreenTile[];\n}\n\nexport interface ScreenTile {\n id: string;\n row: number;\n col: number;\n x: number;\n y: number;\n width: number;\n height: number;\n data?: Buffer;\n analysis?: TileAnalysis;\n}\n\nexport interface TileAnalysis {\n timestamp: number;\n florence2?: Florence2Result;\n ocr?: OCRResult;\n objects?: DetectedObject[];\n text?: string;\n summary?: string;\n}\n\nexport interface Florence2Result {\n caption?: string;\n objects?: Array<{\n label: string;\n bbox: BoundingBox;\n confidence: number;\n }>;\n regions?: Array<{\n description: string;\n bbox: BoundingBox;\n }>;\n tags?: string[];\n}\n\nexport interface OCRResult {\n text: string;\n blocks: Array<{\n text: string;\n bbox: BoundingBox;\n confidence: number;\n words?: Array<{\n text: string;\n bbox: BoundingBox;\n confidence: number;\n }>;\n }>;\n fullText: string;\n}\n\nexport interface EnhancedSceneDescription extends SceneDescription {\n screenCapture?: ScreenCapture;\n screenAnalysis?: {\n fullScreenOCR?: string;\n activeTile?: TileAnalysis;\n gridSummary?: string;\n focusedApp?: string;\n uiElements?: Array<{\n type: string;\n text: string;\n position: BoundingBox;\n }>;\n };\n}\n\nexport interface VisionConfig {\n cameraName?: string;\n pixelChangeThreshold?: number;\n updateInterval?: number;\n enablePoseDetection?: boolean;\n enableObjectDetection?: boolean;\n tfUpdateInterval?: number;\n vlmUpdateInterval?: number;\n tfChangeThreshold?: number;\n vlmChangeThreshold?: number;\n visionMode?: VisionMode;\n screenCaptureInterval?: number;\n tileSize?: number;\n tileProcessingOrder?: \"sequential\" | \"priority\" | \"random\";\n ocrEnabled?: boolean;\n florence2Enabled?: boolean;\n screenRegion?: {\n x: number;\n y: number;\n width: number;\n height: number;\n };\n displayIndex?: number;\n captureAllDisplays?: boolean;\n targetScreenFPS?: number;\n textRegions?: Array<{\n x: number;\n y: number;\n width: number;\n height: number;\n }>;\n}\n\nexport interface TrackedEntity {\n id: string;\n entityType: \"person\" | \"object\" | \"pet\";\n firstSeen: number;\n lastSeen: number;\n lastPosition: BoundingBox;\n appearances: EntityAppearance[];\n attributes: EntityAttributes;\n worldId?: string;\n roomId?: string;\n}\n\nexport interface EntityAppearance {\n timestamp: number;\n boundingBox: BoundingBox;\n confidence: number;\n embedding?: number[]; // Face embedding for person recognition\n keypoints?: Array<{\n part: string;\n position: { x: number; y: number };\n score: number;\n }>;\n}\n\nexport interface EntityAttributes {\n [key: string]: string | number | boolean | null | undefined | string[] | number[];\n name?: string;\n faceEmbedding?: number[];\n faceId?: string;\n clothing?: string[];\n hairColor?: string;\n accessories?: string[];\n\n // For objects\n objectType?: string;\n color?: string;\n size?: \"small\" | \"medium\" | \"large\";\n description?: string;\n tags?: string[];\n}\n\nexport interface FaceLibrary {\n faces: Map<string, FaceProfile>;\n embeddings: Map<string, number[][]>; // Multiple embeddings per profile\n}\n\nexport interface FaceProfile {\n id: string;\n name?: string;\n embeddings: number[][]; // Multiple embeddings for better recognition\n firstSeen: number;\n lastSeen: number;\n seenCount: number;\n attributes?: {\n age?: string;\n gender?: string;\n emotion?: string;\n };\n}\n\nexport interface WorldState {\n worldId: string;\n entities: Map<string, TrackedEntity>;\n lastUpdate: number;\n activeEntities: string[];\n recentlyLeft: Array<{\n entityId: string;\n leftAt: number;\n lastPosition: BoundingBox;\n }>;\n}\n",
7
- "import {\n addHeader,\n type IAgentRuntime,\n logger,\n type Memory,\n type Provider,\n type State,\n} from \"@elizaos/core\";\nimport type { VisionService } from \"./service\";\nimport type { BoundingBox, EnhancedSceneDescription, EntityAttributes } from \"./types\";\n\nexport const visionProvider: Provider = {\n name: \"VISION_PERCEPTION\",\n description:\n \"Provides current visual perception data including scene description, detected objects, people, and entity tracking. This provider is always active and provides real-time visual awareness.\",\n position: 99,\n dynamic: false,\nget: async (runtime: IAgentRuntime, message: Memory, _state: State) => {\n\nconst visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService) {\n logger.warn(\"[visionProvider] VisionService not found.\");\n return {\n values: {\n visionAvailable: false,\n sceneDescription: \"Vision service is not available.\",\n cameraStatus: \"No camera connected\",\n },\n text: addHeader(\"# Visual Perception\", \"Vision service is not available.\"),\n data: { hasVision: false },\n };\n }\n\n const sceneDescription =\n (await visionService.getEnhancedSceneDescription()) ||\n (await visionService.getSceneDescription());\n const cameraInfo = visionService.getCameraInfo();\n const isActive = visionService.isActive();\n const visionMode = visionService.getVisionMode();\n const screenCapture = await visionService.getScreenCapture();\n const _worldId = message.worldId || \"default-world\";\n const entityTracker = visionService.getEntityTracker();\n\n let entityData: {\n activeEntities: Array<{\n id: string;\n type: \"person\" | \"object\" | \"pet\";\n name: string | undefined;\n firstSeen: number;\n duration: number;\n position: BoundingBox;\n attributes: EntityAttributes;\n }>;\n recentlyLeft: Array<{\n id: string;\n name: string | undefined;\n leftAt: number;\n timeAgo: number;\n }>;\n statistics: {\n totalEntities: number;\n activeEntities: number;\n recentlyLeft: number;\n people: number;\n objects: number;\n };\n } | null = null;\n\n if (sceneDescription && entityTracker) {\n await entityTracker.updateEntities(\n sceneDescription.objects,\n sceneDescription.people,\n undefined,\n runtime\n );\n\n const activeEntities = entityTracker.getActiveEntities();\n const recentlyLeft = entityTracker.getRecentlyLeft();\n const stats = entityTracker.getStatistics();\n\n entityData = {\n activeEntities: activeEntities.map((e) => ({\n id: e.id,\n type: e.entityType,\n name: e.attributes.name,\n firstSeen: e.firstSeen,\n duration: Date.now() - e.firstSeen,\n position: e.lastPosition,\n attributes: e.attributes,\n })),\n recentlyLeft: recentlyLeft.map(({ entity, leftAt }) => ({\n id: entity.id,\n name: entity.attributes.name,\n leftAt,\n timeAgo: Date.now() - leftAt,\n })),\n statistics: stats,\n };\n }\n\n let perceptionText = \"\";\n let values = {};\n let data = {};\n\n if (!isActive) {\n perceptionText = `Vision mode: ${visionMode}\\n`;\n if (visionMode === \"OFF\") {\n perceptionText += \"Vision is disabled.\";\n } else {\n perceptionText += \"Vision service is initializing...\";\n }\n\n values = {\n visionAvailable: false,\n visionMode,\n sceneDescription: \"Vision not active\",\n cameraStatus: cameraInfo\n ? `Camera \"${cameraInfo.name}\" detected but not active`\n : \"No camera\",\n };\n } else {\n perceptionText = `Vision mode: ${visionMode}\\n\\n`;\n\n if ((visionMode === \"CAMERA\" || visionMode === \"BOTH\") && sceneDescription) {\n const ageInSeconds = (Date.now() - sceneDescription.timestamp) / 1000;\n const secondsAgo = Math.round(ageInSeconds);\n\n perceptionText += `Camera view (${secondsAgo}s ago):\\n${sceneDescription.description}`;\n\n if (sceneDescription.people.length > 0) {\n perceptionText += `\\n\\nPeople detected: ${sceneDescription.people.length}`;\n const poses = sceneDescription.people.map((p) => p.pose).filter((p) => p !== \"unknown\");\n const facings = sceneDescription.people\n .map((p) => p.facing)\n .filter((f) => f !== \"unknown\");\n\n if (poses.length > 0) {\n const poseCounts = poses.reduce(\n (acc, pose) => {\n acc[pose] = (acc[pose] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>\n );\n perceptionText += `\\n Poses: ${Object.entries(poseCounts)\n .map(([pose, count]) => `${count} ${pose}`)\n .join(\", \")}`;\n }\n\n if (facings.length > 0) {\n const facingCounts = facings.reduce(\n (acc, facing) => {\n acc[facing] = (acc[facing] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>\n );\n perceptionText += `\\n Facing: ${Object.entries(facingCounts)\n .map(([facing, count]) => `${count} facing ${facing}`)\n .join(\", \")}`;\n }\n }\n\n if (sceneDescription.objects.length > 0) {\n const objectTypes = sceneDescription.objects.map((o) => o.type);\n const uniqueObjects = [...new Set(objectTypes)];\n perceptionText += `\\n\\nObjects detected: ${uniqueObjects.join(\", \")}`;\n }\n\n if (sceneDescription.sceneChanged) {\n perceptionText += `\\n\\nScene change: ${sceneDescription.changePercentage.toFixed(1)}% of pixels changed`;\n }\n\n if (entityData) {\n if (entityData.activeEntities.length > 0) {\n perceptionText += \"\\n\\nCurrently tracking:\";\n for (const entity of entityData.activeEntities) {\n const name = entity.name || `Unknown ${entity.type}`;\n const duration =\n entity.duration < 60000\n ? `${Math.round(entity.duration / 1000)}s`\n : `${Math.round(entity.duration / 60000)}m`;\n perceptionText += `\\n- ${name} (present for ${duration})`;\n }\n }\n\n if (entityData.recentlyLeft.length > 0) {\n perceptionText += \"\\n\\nRecently left:\";\n for (const departed of entityData.recentlyLeft) {\n const name = departed.name || \"Unknown person\";\n const timeStr =\n departed.timeAgo < 60000\n ? `${Math.round(departed.timeAgo / 1000)}s ago`\n : `${Math.round(departed.timeAgo / 60000)}m ago`;\n perceptionText += `\\n- ${name} left ${timeStr}`;\n }\n }\n }\n }\n\n if ((visionMode === \"SCREEN\" || visionMode === \"BOTH\") && screenCapture) {\n const screenAge = (Date.now() - screenCapture.timestamp) / 1000;\n const screenSecondsAgo = Math.round(screenAge);\n\n if (visionMode === \"BOTH\") {\n perceptionText += \"\\n\\n---\\n\\n\";\n }\n\n perceptionText += `Screen capture (${screenSecondsAgo}s ago):\\n`;\n perceptionText += `Resolution: ${screenCapture.width}x${screenCapture.height}\\n`;\n\n const enhanced = sceneDescription as EnhancedSceneDescription;\n if (enhanced?.screenAnalysis) {\n const tileAnalysis = enhanced.screenAnalysis.activeTile;\n if (tileAnalysis) {\n if (tileAnalysis.summary) {\n perceptionText += `\\nActive area: ${tileAnalysis.summary}`;\n }\n\n if (tileAnalysis.text) {\n perceptionText += `\\n\\nVisible text:\\n\"${tileAnalysis.text.substring(0, 200)}${tileAnalysis.text.length > 200 ? \"...\" : \"\"}\"`;\n }\n\n if (tileAnalysis.objects && tileAnalysis.objects.length > 0) {\n const uiElements = tileAnalysis.objects.map(\n (o) => (o as { type?: string }).type || \"unknown\"\n );\n const uniqueElements = [...new Set(uiElements)];\n perceptionText += `\\n\\nUI elements: ${uniqueElements.join(\", \")}`;\n }\n }\n\n if (enhanced.screenAnalysis.focusedApp) {\n perceptionText += `\\n\\nActive application: ${enhanced.screenAnalysis.focusedApp}`;\n }\n }\n }\n\n values = {\n visionAvailable: true,\n visionMode,\n sceneDescription: sceneDescription?.description || \"Processing...\",\n cameraStatus: cameraInfo ? `Connected to ${cameraInfo.name}` : \"No camera\",\n cameraId: cameraInfo?.id,\n peopleCount: sceneDescription?.people.length || 0,\n objectCount: sceneDescription?.objects.length || 0,\n sceneAge: sceneDescription\n ? Math.round((Date.now() - sceneDescription.timestamp) / 1000)\n : null,\n lastChange: sceneDescription?.sceneChanged ? sceneDescription.changePercentage : 0,\n hasScreenCapture: !!screenCapture,\n screenResolution: screenCapture ? `${screenCapture.width}x${screenCapture.height}` : null,\n activeEntities: entityData?.activeEntities || [],\n recentlyLeft: entityData?.recentlyLeft || [],\n entityStatistics: entityData?.statistics || null,\n };\n\n data = {\n objects: sceneDescription?.objects || [],\n people: sceneDescription?.people || [],\n screenCapture: screenCapture || null,\n enhancedData: (sceneDescription as EnhancedSceneDescription)?.screenAnalysis || null,\n trackedEntities: entityData?.activeEntities || [],\n worldState: entityData || null,\n };\n }\n\n return {\n values,\n text: addHeader(\"# Visual Perception\", perceptionText),\n data,\n };\n },\n};\n",
8
- "// Vision service for camera integration and scene analysis\n\nimport { exec } from \"node:child_process\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport {\n type IAgentRuntime,\n logger,\n ModelType,\n Service,\n type ServiceTypeName,\n} from \"@elizaos/core\";\nimport sharp from \"sharp\";\nimport { AudioCaptureService, type AudioConfig } from \"./audio-capture\";\nimport { StreamingAudioCaptureService, type StreamingAudioConfig } from \"./audio-capture-stream\";\nimport { EntityTracker } from \"./entity-tracker\";\nimport { FaceRecognition } from \"./face-recognition\";\nimport { Florence2Model } from \"./florence2-model\";\nimport { OCRService } from \"./ocr-service\";\nimport { ScreenCaptureService } from \"./screen-capture\";\nimport {\n type BoundingBox,\n type CameraInfo,\n type DetectedObject,\n type EnhancedSceneDescription,\n type PersonInfo,\n type SceneDescription,\n type ScreenCapture,\n type ScreenTile,\n type TileAnalysis,\n type VisionConfig,\n type VisionFrame,\n VisionMode,\n VisionServiceType,\n} from \"./types\";\nimport { VisionModels } from \"./vision-models\";\nimport { VisionWorkerManager } from \"./vision-worker-manager\";\n\nconst execAsync = promisify(exec);\n\ninterface CameraDevice {\n id: string;\n name: string;\n capture: () => Promise<Buffer>;\n}\n\nexport class VisionService extends Service {\n static override serviceType: ServiceTypeName = VisionServiceType.VISION;\n override capabilityDescription =\n \"Provides visual perception through camera integration and scene analysis.\";\n\n private visionConfig: VisionConfig;\n private camera: CameraDevice | null = null;\n private lastFrame: VisionFrame | null = null;\n private lastSceneDescription: SceneDescription | null = null;\n private frameProcessingInterval: NodeJS.Timeout | null = null;\n private screenProcessingInterval: NodeJS.Timeout | null = null;\n private isProcessing = false;\n private isProcessingScreen = false;\n private visionModels: VisionModels;\n private faceRecognition: FaceRecognition;\n private entityTracker: EntityTracker;\n private audioCapture: AudioCaptureService | null = null;\n private streamingAudioCapture: StreamingAudioCaptureService | null = null;\n\n // Screen vision components\n private screenCapture: ScreenCaptureService;\n private florence2: Florence2Model;\n private ocrService: OCRService;\n private lastScreenCapture: ScreenCapture | null = null;\n private lastEnhancedScene: EnhancedSceneDescription | null = null;\n\n // Worker manager for high-FPS processing\n private workerManager: VisionWorkerManager | null = null;\n\n // Add tracking for last update times\n private lastTfUpdateTime = 0;\n private lastVlmUpdateTime = 0;\n private lastTfDescription = \"\";\n\n // Default configuration\n private readonly DEFAULT_CONFIG: VisionConfig = {\n pixelChangeThreshold: 50, // 50% change required for VLM update\n updateInterval: 100, // Process frames every 100ms\n enablePoseDetection: false,\n enableObjectDetection: false,\n tfUpdateInterval: 1000, // TensorFlow update every 1 second\n vlmUpdateInterval: 10000, // VLM update every 10 seconds\n tfChangeThreshold: 10, // 10% change triggers TF update\n vlmChangeThreshold: 50, // 50% change triggers VLM update\n visionMode: VisionMode.CAMERA, // Default to camera only\n screenCaptureInterval: 2000, // Screen capture every 2 seconds\n tileSize: 256,\n tileProcessingOrder: \"priority\",\n ocrEnabled: true,\n florence2Enabled: true,\n };\n\n constructor(runtime: IAgentRuntime) {\n super(runtime);\n\n // Load configuration from runtime settings\n this.visionConfig = this.parseConfig(runtime);\n\n // Initialize vision models\n this.visionModels = new VisionModels();\n\n // Initialize face recognition\n this.faceRecognition = new FaceRecognition();\n\n // Initialize entity tracker\n const worldIdValue = runtime.getSetting(\"WORLD_ID\");\n const worldId = typeof worldIdValue === \"string\" ? worldIdValue : \"default-world\";\n this.entityTracker = new EntityTracker(worldId);\n\n // Initialize screen capture\n this.screenCapture = new ScreenCaptureService(this.visionConfig);\n\n // Initialize Florence-2\n this.florence2 = new Florence2Model();\n\n // Initialize OCR service\n this.ocrService = new OCRService();\n\n logger.info(\"[VisionService] Constructed with config:\", JSON.stringify(this.visionConfig));\n }\n\n private parseConfig(runtime: IAgentRuntime): VisionConfig {\n const getSettingString = (key: string): string | undefined => {\n const value = runtime.getSetting(key);\n return value === true || value === false\n ? String(value)\n : typeof value === \"string\"\n ? value\n : typeof value === \"number\"\n ? String(value)\n : undefined;\n };\n\n return {\n ...this.DEFAULT_CONFIG,\n cameraName: getSettingString(\"CAMERA_NAME\") || getSettingString(\"VISION_CAMERA_NAME\"),\n pixelChangeThreshold:\n Number(\n runtime.getSetting(\"PIXEL_CHANGE_THRESHOLD\") ||\n runtime.getSetting(\"VISION_PIXEL_CHANGE_THRESHOLD\")\n ) || this.DEFAULT_CONFIG.pixelChangeThreshold,\n enableObjectDetection:\n runtime.getSetting(\"ENABLE_OBJECT_DETECTION\") === \"true\" ||\n runtime.getSetting(\"VISION_ENABLE_OBJECT_DETECTION\") === \"true\",\n enablePoseDetection:\n runtime.getSetting(\"ENABLE_POSE_DETECTION\") === \"true\" ||\n runtime.getSetting(\"VISION_ENABLE_POSE_DETECTION\") === \"true\",\n tfUpdateInterval:\n Number(\n runtime.getSetting(\"TF_UPDATE_INTERVAL\") ||\n runtime.getSetting(\"VISION_TF_UPDATE_INTERVAL\")\n ) || this.DEFAULT_CONFIG.tfUpdateInterval,\n vlmUpdateInterval:\n Number(\n runtime.getSetting(\"VLM_UPDATE_INTERVAL\") ||\n runtime.getSetting(\"VISION_VLM_UPDATE_INTERVAL\")\n ) || this.DEFAULT_CONFIG.vlmUpdateInterval,\n tfChangeThreshold:\n Number(\n runtime.getSetting(\"TF_CHANGE_THRESHOLD\") ||\n runtime.getSetting(\"VISION_TF_CHANGE_THRESHOLD\")\n ) || this.DEFAULT_CONFIG.tfChangeThreshold,\n vlmChangeThreshold:\n Number(\n runtime.getSetting(\"VLM_CHANGE_THRESHOLD\") ||\n runtime.getSetting(\"VISION_VLM_CHANGE_THRESHOLD\")\n ) || this.DEFAULT_CONFIG.vlmChangeThreshold,\n visionMode: (getSettingString(\"VISION_MODE\") as VisionMode) || this.DEFAULT_CONFIG.visionMode,\n screenCaptureInterval:\n Number(\n runtime.getSetting(\"SCREEN_CAPTURE_INTERVAL\") ||\n runtime.getSetting(\"VISION_SCREEN_CAPTURE_INTERVAL\")\n ) || this.DEFAULT_CONFIG.screenCaptureInterval,\n ocrEnabled:\n getSettingString(\"OCR_ENABLED\") === \"true\" ||\n getSettingString(\"VISION_OCR_ENABLED\") === \"true\",\n florence2Enabled:\n getSettingString(\"FLORENCE2_ENABLED\") === \"true\" ||\n getSettingString(\"VISION_FLORENCE2_ENABLED\") === \"true\",\n };\n }\n\n static async start(runtime: IAgentRuntime): Promise<VisionService> {\n const service = new VisionService(runtime);\n await service.initialize();\n return service;\n }\n\n private async checkCameraTools(): Promise<{ available: boolean; tool: string }> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // Check if imagesnap is installed\n await execAsync(\"which imagesnap\");\n return { available: true, tool: \"imagesnap\" };\n } else if (platform === \"linux\") {\n // Check if fswebcam is installed\n await execAsync(\"which fswebcam\");\n return { available: true, tool: \"fswebcam\" };\n } else if (platform === \"win32\") {\n // Check if ffmpeg is available\n await execAsync(\"where ffmpeg\");\n return { available: true, tool: \"ffmpeg\" };\n }\n return { available: false, tool: \"none\" };\n } catch (_error) {\n // Tool not found\n return { available: false, tool: \"none\" };\n }\n }\n\n private async initialize(): Promise<void> {\n try {\n // Initialize vision models if enabled\n const useEnhancedModels =\n this.visionConfig.enableObjectDetection || this.visionConfig.enablePoseDetection;\n\n if (useEnhancedModels) {\n try {\n // Try to initialize TensorFlow models first\n await this.visionModels.initialize({\n enableObjectDetection: this.visionConfig.enableObjectDetection || false,\n enablePoseDetection: this.visionConfig.enablePoseDetection || false,\n });\n logger.info(\"[VisionService] Using TensorFlow.js models for advanced detection\");\n } catch (_tfError) {\n logger.warn(\n \"[VisionService] TensorFlow.js not available, falling back to enhanced heuristics\"\n );\n // Fall back to enhanced heuristics\n await this.visionModels.initialize({\n enableObjectDetection: this.visionConfig.enableObjectDetection || false,\n enablePoseDetection: this.visionConfig.enablePoseDetection || false,\n });\n logger.info(\"[VisionService] Using enhanced heuristics for detection\");\n }\n }\n\n // Initialize screen vision if enabled\n if (\n this.visionConfig.visionMode === VisionMode.SCREEN ||\n this.visionConfig.visionMode === VisionMode.BOTH\n ) {\n await this.initializeScreenVision();\n }\n\n // Initialize camera if enabled\n if (\n this.visionConfig.visionMode === VisionMode.CAMERA ||\n this.visionConfig.visionMode === VisionMode.BOTH\n ) {\n await this.initializeCameraVision();\n }\n\n // Initialize audio capture if enabled\n await this.initializeAudioCapture();\n\n // Start processing based on mode\n this.startProcessing();\n } catch (error) {\n logger.error(\"[VisionService] Failed to initialize:\", error);\n }\n }\n\n private async initializeScreenVision(): Promise<void> {\n try {\n logger.info(\"[VisionService] Initializing screen vision...\");\n\n // Check if we should use worker threads for high-FPS processing\n const useWorkers =\n this.visionConfig.targetScreenFPS && this.visionConfig.targetScreenFPS > 10;\n\n if (useWorkers) {\n // Initialize worker manager for high-FPS processing\n logger.info(\"[VisionService] Initializing worker threads for high-FPS processing...\");\n this.workerManager = new VisionWorkerManager(this.visionConfig);\n await this.workerManager.initialize();\n logger.info(\"[VisionService] Worker threads initialized\");\n } else {\n // Initialize standard components\n // Initialize Florence-2 if enabled\n if (this.visionConfig.florence2Enabled) {\n await this.florence2.initialize();\n }\n\n // Initialize OCR if enabled\n if (this.visionConfig.ocrEnabled) {\n await this.ocrService.initialize();\n }\n }\n\n // Get screen info\n const screenInfo = await this.screenCapture.getScreenInfo();\n if (screenInfo) {\n logger.info(`[VisionService] Screen resolution: ${screenInfo.width}x${screenInfo.height}`);\n }\n\n logger.info(\"[VisionService] Screen vision initialized\");\n } catch (error) {\n logger.error(\"[VisionService] Failed to initialize screen vision:\", error);\n }\n }\n\n private async initializeCameraVision(): Promise<void> {\n // Check if camera tools are available\n const toolCheck = await this.checkCameraTools();\n if (!toolCheck.available) {\n const platform = process.platform;\n const toolName =\n platform === \"darwin\" ? \"imagesnap\" : platform === \"linux\" ? \"fswebcam\" : \"ffmpeg\";\n logger.warn(\n `[VisionService] Camera capture tool '${toolName}' not found. Install it to enable camera functionality.`\n );\n logger.warn(\"[VisionService] For macOS: brew install imagesnap\");\n logger.warn(\"[VisionService] For Linux: sudo apt-get install fswebcam\");\n logger.warn(\"[VisionService] For Windows: Install ffmpeg and add to PATH\");\n return;\n }\n\n // Find and connect to camera\n const camera = await this.findCamera();\n if (camera) {\n this.camera = camera;\n logger.info(`[VisionService] Connected to camera: ${camera.name}`);\n } else {\n logger.warn(\"[VisionService] No suitable camera found\");\n }\n }\n\n private async initializeAudioCapture(): Promise<void> {\n const getSettingString = (key: string): string | undefined => {\n const value = this.runtime.getSetting(key);\n return value === true || value === false\n ? String(value)\n : typeof value === \"string\"\n ? value\n : typeof value === \"number\"\n ? String(value)\n : undefined;\n };\n const enableMicrophone = getSettingString(\"ENABLE_MICROPHONE\") === \"true\";\n const useStreamingAudio = getSettingString(\"USE_STREAMING_AUDIO\") === \"true\";\n\n if (!enableMicrophone) {\n logger.info(\"[VisionService] Microphone capture disabled\");\n return;\n }\n\n try {\n if (useStreamingAudio) {\n // Use new streaming audio with VAD\n const getSettingNumber = (key: string, defaultValue: number): number => {\n const value = this.runtime.getSetting(key);\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\") {\n const parsed = Number(value);\n return Number.isNaN(parsed) ? defaultValue : parsed;\n }\n return defaultValue;\n };\n const streamingConfig: StreamingAudioConfig = {\n enabled: true,\n sampleRate: 16000,\n channels: 1,\n vadThreshold: getSettingNumber(\"VAD_THRESHOLD\", 0.01),\n silenceTimeout: getSettingNumber(\"SILENCE_TIMEOUT\", 1500),\n responseDelay: getSettingNumber(\"RESPONSE_DELAY\", 3000),\n };\n\n this.streamingAudioCapture = new StreamingAudioCaptureService(\n this.runtime,\n streamingConfig\n );\n\n // Set up event listeners\n this.streamingAudioCapture.on(\"speechStart\", () => {\n logger.info(\"[VisionService] User started speaking\");\n });\n\n this.streamingAudioCapture.on(\"speechEnd\", () => {\n logger.info(\"[VisionService] User stopped speaking\");\n });\n\n this.streamingAudioCapture.on(\n \"transcription\",\n (data: { text: string; isFinal: boolean }) => {\n logger.info(\n `[VisionService] Transcription (${data.isFinal ? \"final\" : \"partial\"}): ${data.text}`\n );\n }\n );\n\n this.streamingAudioCapture.on(\"utteranceComplete\", async (text: string) => {\n logger.info(\"[VisionService] Processing complete utterance:\", text);\n // Store the transcription in memory for context\n await this.storeAudioTranscription(text);\n });\n\n await this.streamingAudioCapture.initialize();\n logger.info(\"[VisionService] Streaming audio capture initialized with VAD\");\n } else {\n // Use original batch audio capture\n const getSettingNumber = (key: string, defaultValue: number): number => {\n const value = this.runtime.getSetting(key);\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\") {\n const parsed = Number(value);\n return Number.isNaN(parsed) ? defaultValue : parsed;\n }\n return defaultValue;\n };\n const audioConfig: AudioConfig = {\n enabled: true,\n transcriptionInterval: getSettingNumber(\"TRANSCRIPTION_INTERVAL\", 30000),\n };\n\n this.audioCapture = new AudioCaptureService(this.runtime, audioConfig);\n await this.audioCapture.initialize();\n logger.info(\"[VisionService] Batch audio capture initialized\");\n }\n } catch (error) {\n logger.error(\"[VisionService] Failed to initialize audio capture:\", error);\n // Continue without audio\n }\n }\n\n private async storeAudioTranscription(text: string): Promise<void> {\n try {\n // Store transcription in the current scene description\n if (this.lastSceneDescription) {\n this.lastSceneDescription.audioTranscription = text;\n }\n\n // You could also create a memory here if needed\n logger.debug(\"[VisionService] Stored audio transcription in scene context\");\n } catch (error) {\n logger.error(\"[VisionService] Failed to store audio transcription:\", error);\n }\n }\n\n private startProcessing(): void {\n // Start camera processing if enabled\n if (\n (this.visionConfig.visionMode === VisionMode.CAMERA ||\n this.visionConfig.visionMode === VisionMode.BOTH) &&\n this.camera\n ) {\n this.startFrameProcessing();\n }\n\n // Start screen processing if enabled\n if (\n this.visionConfig.visionMode === VisionMode.SCREEN ||\n this.visionConfig.visionMode === VisionMode.BOTH\n ) {\n this.startScreenProcessing();\n }\n }\n\n private startFrameProcessing(): void {\n if (this.frameProcessingInterval) {\n return;\n }\n\n this.frameProcessingInterval = setInterval(async () => {\n if (!this.isProcessing && this.camera) {\n this.isProcessing = true;\n try {\n await this.captureAndProcessFrame();\n } catch (error) {\n logger.error(\"[VisionService] Frame processing error:\", error);\n }\n this.isProcessing = false;\n }\n }, this.visionConfig.updateInterval || 100);\n\n logger.debug(\"[VisionService] Started frame processing loop\");\n }\n\n private async captureAndProcessFrame(): Promise<void> {\n if (!this.camera) {\n return;\n }\n\n try {\n // Capture frame from camera\n const frameData = await this.camera.capture();\n\n // Skip if no data\n if (!frameData || frameData.length === 0) {\n logger.debug(\"[VisionService] Camera returned empty frame, skipping\");\n return;\n }\n\n // Convert to standardized format\n const frame = await this.processFrameData(frameData);\n\n // Validate frame before processing\n if (!frame || frame.width === 0 || frame.height === 0) {\n logger.warn(\"[VisionService] Invalid frame dimensions, skipping\");\n return;\n }\n\n // Check if scene has changed significantly\n const changePercentage = this.lastFrame\n ? await this.calculatePixelChange(this.lastFrame, frame)\n : 100;\n\n // Update scene description if change is significant or enough time has passed\n // Always call updateSceneDescription - it will decide what to update based on thresholds\n await this.updateSceneDescription(frame, changePercentage);\n\n this.lastFrame = frame;\n } catch (error) {\n logger.error(\"[VisionService] Error capturing frame:\", error);\n }\n }\n\n private async processFrameData(data: Buffer): Promise<VisionFrame> {\n // Validate input data\n if (!data || data.length === 0) {\n throw new Error(\"Empty frame data received from camera\");\n }\n\n // Use sharp to ensure consistent format\n const image = sharp(data);\n const metadata = await image.metadata();\n\n // Validate metadata\n if (!metadata.width || !metadata.height || metadata.width === 0 || metadata.height === 0) {\n throw new Error(`Invalid image dimensions: ${metadata.width}x${metadata.height}`);\n }\n\n const rgbaBuffer = await image.ensureAlpha().raw().toBuffer();\n\n return {\n timestamp: Date.now(),\n width: metadata.width,\n height: metadata.height,\n data: rgbaBuffer,\n format: \"rgba\",\n };\n }\n\n private async calculatePixelChange(frame1: VisionFrame, frame2: VisionFrame): Promise<number> {\n if (frame1.width !== frame2.width || frame1.height !== frame2.height) {\n return 100; // Different dimensions = complete change\n }\n\n const pixels1 = frame1.data;\n const pixels2 = frame2.data;\n let changedPixels = 0;\n const totalPixels = frame1.width * frame1.height;\n const threshold = 30; // RGB difference threshold\n\n for (let i = 0; i < pixels1.length; i += 4) {\n const r1 = pixels1[i];\n const g1 = pixels1[i + 1];\n const b1 = pixels1[i + 2];\n const r2 = pixels2[i];\n const g2 = pixels2[i + 1];\n const b2 = pixels2[i + 2];\n\n const diff = Math.abs(r1 - r2) + Math.abs(g1 - g2) + Math.abs(b1 - b2);\n if (diff > threshold) {\n changedPixels++;\n }\n }\n\n return (changedPixels / totalPixels) * 100;\n }\n\n private async updateSceneDescription(\n frame: VisionFrame,\n changePercentage: number\n ): Promise<void> {\n try {\n const currentTime = Date.now();\n\n // Convert frame to base64 for VLM\n const jpegBuffer = await sharp(frame.data, {\n raw: {\n width: frame.width,\n height: frame.height,\n channels: 4,\n },\n })\n .jpeg()\n .toBuffer();\n\n const base64Image = jpegBuffer.toString(\"base64\");\n const imageUrl = `data:image/jpeg;base64,${base64Image}`;\n\n // Determine if we should update VLM description\n const timeSinceVlmUpdate = currentTime - this.lastVlmUpdateTime;\n const vlmUpdateInterval = this.visionConfig.vlmUpdateInterval ?? 10000;\n const vlmChangeThreshold = this.visionConfig.vlmChangeThreshold ?? 50;\n const shouldUpdateVlm =\n timeSinceVlmUpdate >= vlmUpdateInterval || // Time threshold\n changePercentage >= vlmChangeThreshold; // Change threshold\n\n let description = this.lastTfDescription;\n\n if (shouldUpdateVlm) {\n // Use VLM to describe the scene\n description = await this.describeSceneWithVLM(imageUrl);\n this.lastVlmUpdateTime = currentTime;\n this.lastTfDescription = description;\n logger.debug(\n `[VisionService] VLM updated: ${timeSinceVlmUpdate}ms since last update, ${changePercentage.toFixed(1)}% change`\n );\n }\n\n // Determine if we should update TensorFlow detections\n const timeSinceTfUpdate = currentTime - this.lastTfUpdateTime;\n const tfUpdateInterval = this.visionConfig.tfUpdateInterval ?? 1000;\n const tfChangeThreshold = this.visionConfig.tfChangeThreshold ?? 10;\n const shouldUpdateTf =\n timeSinceTfUpdate >= tfUpdateInterval || // Time threshold\n changePercentage >= tfChangeThreshold; // Change threshold\n\n let detectedObjects: DetectedObject[] = [];\n let people: PersonInfo[] = [];\n\n if (\n shouldUpdateTf &&\n (this.visionConfig.enableObjectDetection || this.visionConfig.enablePoseDetection)\n ) {\n this.lastTfUpdateTime = currentTime;\n logger.debug(\n `[VisionService] TF updating: ${timeSinceTfUpdate}ms since last update, ${changePercentage.toFixed(1)}% change`\n );\n\n // Use advanced computer vision if enabled\n if (this.visionConfig.enableObjectDetection) {\n if (this.visionModels.hasObjectDetection()) {\n detectedObjects = await this.visionModels.detectObjects(\n frame.data,\n frame.width,\n frame.height\n );\n logger.debug(`[VisionService] VisionModels detected ${detectedObjects.length} objects`);\n }\n }\n\n if (this.visionConfig.enablePoseDetection) {\n if (this.visionModels.hasPoseDetection()) {\n const poses = await this.visionModels.detectPoses(\n frame.data,\n frame.width,\n frame.height\n );\n people = poses;\n logger.debug(\n `[VisionService] VisionModels detected ${people.length} people with poses`\n );\n }\n }\n\n // If no people detected via pose but objects detected, check for person objects\n if (people.length === 0 && detectedObjects.length > 0) {\n const personObjects = detectedObjects.filter((obj) => obj.type === \"person\");\n people = personObjects.map((obj) => ({\n id: `person-${obj.id}`,\n pose: \"unknown\" as const,\n facing: \"unknown\" as const,\n confidence: obj.confidence,\n boundingBox: obj.boundingBox,\n }));\n }\n } else if (!shouldUpdateTf && this.lastSceneDescription) {\n // Reuse last detection results if not updating\n detectedObjects = this.lastSceneDescription.objects;\n people = this.lastSceneDescription.people;\n } else {\n // Fall back to motion-based detection\n detectedObjects = await this.detectMotionObjects(frame);\n people = await this.detectPeopleFromMotion(frame, detectedObjects);\n }\n\n // Face recognition and entity tracking\n const faceProfiles = new Map<string, string>();\n const getSettingString = (key: string): string | undefined => {\n const value = this.runtime.getSetting(key);\n return value === true || value === false\n ? String(value)\n : typeof value === \"string\"\n ? value\n : typeof value === \"number\"\n ? String(value)\n : undefined;\n };\n const enableFaceRecognition = getSettingString(\"ENABLE_FACE_RECOGNITION\") === \"true\";\n\n if (enableFaceRecognition && people.length > 0 && frame.width > 0 && frame.height > 0) {\n try {\n // Validate frame data\n if (!frame.data || frame.data.length === 0) {\n logger.warn(\"[VisionService] Invalid frame data for face recognition\");\n return;\n }\n\n // Detect faces in the frame\n const faces = await this.faceRecognition.detectFaces(\n frame.data,\n frame.width,\n frame.height\n );\n\n // Match faces to people based on bounding box overlap\n for (const face of faces) {\n const faceBox = face.detection.box;\n\n // Find the person this face belongs to\n for (const person of people) {\n const overlap = this.calculateBoxOverlap(person.boundingBox, {\n x: Math.round(faceBox.x),\n y: Math.round(faceBox.y),\n width: Math.round(faceBox.width),\n height: Math.round(faceBox.height),\n });\n\n if (overlap > 0.5) {\n // 50% overlap threshold\n // Recognize or register the face\n const match = await this.faceRecognition.recognizeFace(face.descriptor);\n let profileId: string;\n\n if (match) {\n profileId = match.profileId;\n logger.debug(\n `[VisionService] Recognized face: ${profileId} (distance: ${match.distance})`\n );\n } else {\n // Register new face\n profileId = await this.faceRecognition.addOrUpdateFace(face.descriptor, {\n attributes: {\n age: face.ageGender?.age.toString(),\n gender: face.ageGender?.gender,\n emotion: face.expressions\n ? this.getDominantExpression(face.expressions)\n : undefined,\n },\n });\n logger.info(`[VisionService] New face registered: ${profileId}`);\n }\n\n faceProfiles.set(person.id, profileId);\n break;\n }\n }\n }\n } catch (faceError) {\n logger.error(\"[VisionService] Face recognition error:\", faceError);\n }\n }\n\n // Update entity tracker\n const _trackedEntities = await this.entityTracker.updateEntities(\n detectedObjects,\n people,\n faceProfiles,\n this.runtime\n );\n\n // Create scene description\n this.lastSceneDescription = {\n timestamp: frame.timestamp,\n description,\n objects: detectedObjects,\n people,\n sceneChanged: shouldUpdateVlm || shouldUpdateTf,\n changePercentage,\n };\n\n // Enhanced logging\n if (shouldUpdateVlm || shouldUpdateTf) {\n logger.info(\"[VisionService] Scene Analysis Complete:\");\n logger.info(` VLM Description: ${description.substring(0, 100)}...`);\n logger.info(` Change: ${changePercentage.toFixed(1)}%`);\n logger.info(\n ` Updates: ${shouldUpdateVlm ? \"VLM\" : \"\"}${shouldUpdateVlm && shouldUpdateTf ? \" + \" : \"\"}${shouldUpdateTf ? \"TF\" : \"\"}`\n );\n logger.info(\n ` Detection Mode: ${this.visionConfig.enableObjectDetection ? \"Advanced CV\" : \"Motion-based\"}`\n );\n\n if (detectedObjects.length > 0) {\n logger.info(` Objects: ${detectedObjects.length} detected`);\n\n // Group objects by type for summary\n const objectSummary = detectedObjects.reduce(\n (acc, obj) => {\n acc[obj.type] = (acc[obj.type] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>\n );\n\n for (const [type, count] of Object.entries(objectSummary)) {\n logger.info(` - ${count} ${type}(s)`);\n }\n }\n\n if (people.length > 0) {\n logger.info(` People: ${people.length} detected`);\n for (const person of people) {\n logger.info(\n ` - Person: ${person.pose} pose, facing ${person.facing}, confidence: ${person.confidence.toFixed(2)}`\n );\n }\n }\n }\n } catch (error) {\n logger.error(\"[VisionService] Failed to update scene description:\", error);\n }\n }\n\n private async describeSceneWithVLM(imageUrl: string): Promise<string> {\n try {\n // Convert base64 image URL to buffer for Florence-2\n if (imageUrl.startsWith(\"data:image/\")) {\n const base64Data = imageUrl.split(\",\")[1];\n const imageBuffer = Buffer.from(base64Data, \"base64\");\n\n // Use Florence-2 for all image descriptions\n if (this.florence2.isInitialized()) {\n try {\n const result = await this.florence2.analyzeImage(imageBuffer);\n if (result.caption) {\n logger.debug(\"[VisionService] Florence-2 description:\", result.caption);\n return result.caption;\n }\n } catch (florenceError) {\n logger.warn(\"[VisionService] Florence-2 analysis failed, falling back:\", florenceError);\n }\n }\n }\n\n // Fallback to runtime model if Florence-2 is not available\n try {\n const result = await this.runtime.useModel(ModelType.IMAGE_DESCRIPTION, imageUrl);\n\n if (result && typeof result === \"object\" && \"description\" in result) {\n const description = (result as { description: string }).description;\n // Check if we got the unhelpful default response\n if (\n !description.includes(\"I'm unable to analyze images\") &&\n !description.includes(\"I can't analyze images\")\n ) {\n return description;\n }\n } else if (typeof result === \"string\") {\n const stringResult = result as string;\n if (\n stringResult.length > 0 &&\n !stringResult.includes(\"I'm unable to analyze images\") &&\n !stringResult.includes(\"I can't analyze images\")\n ) {\n return stringResult;\n }\n }\n } catch (modelError) {\n logger.warn(\"[VisionService] Runtime IMAGE_DESCRIPTION model failed:\", modelError);\n }\n\n // If we got the unhelpful response or an error, provide a basic description based on detected objects\n if (this.lastSceneDescription) {\n const { objects, people } = this.lastSceneDescription;\n let description = \"Scene contains\";\n\n if (people.length > 0) {\n description += ` ${people.length} person${people.length > 1 ? \"s\" : \"\"}`;\n const poses = people.map((p) => p.pose).filter((p) => p !== \"unknown\");\n if (poses.length > 0) {\n description += ` (${poses.join(\", \")})`;\n }\n }\n\n if (objects.length > 0 && people.length > 0) {\n description += \" and\";\n }\n\n if (objects.length > 0) {\n const objectTypes = [...new Set(objects.map((o) => o.type))];\n description += ` ${objectTypes.join(\", \")}`;\n }\n\n if (people.length === 0 && objects.length === 0) {\n description = \"Scene appears to be empty or static\";\n }\n\n return description;\n }\n\n // Final fallback\n return \"Visual scene captured\";\n } catch (error) {\n logger.error(\"[VisionService] VLM description failed:\", error);\n return \"Unable to describe scene\";\n }\n }\n\n private async detectMotionObjects(frame: VisionFrame): Promise<DetectedObject[]> {\n if (!this.lastFrame) {\n return [];\n }\n\n const objects: DetectedObject[] = [];\n const blockSize = 64; // Larger blocks for less noise\n const motionThreshold = 50; // Higher threshold for more significant changes\n\n // Divide frame into blocks and detect motion regions\n for (let y = 0; y < frame.height - blockSize; y += blockSize / 2) {\n // Overlap blocks\n for (let x = 0; x < frame.width - blockSize; x += blockSize / 2) {\n let blockMotion = 0;\n let pixelCount = 0;\n\n // Check motion in this block\n for (let by = 0; by < blockSize; by += 2) {\n // Sample every other pixel for speed\n for (let bx = 0; bx < blockSize; bx += 2) {\n const px = x + bx;\n const py = y + by;\n const idx = (py * frame.width + px) * 4;\n\n if (idx < frame.data.length && idx < this.lastFrame.data.length) {\n const r1 = frame.data[idx];\n const g1 = frame.data[idx + 1];\n const b1 = frame.data[idx + 2];\n const r2 = this.lastFrame.data[idx];\n const g2 = this.lastFrame.data[idx + 1];\n const b2 = this.lastFrame.data[idx + 2];\n\n const diff = Math.abs(r1 - r2) + Math.abs(g1 - g2) + Math.abs(b1 - b2);\n if (diff > motionThreshold) {\n blockMotion++;\n }\n pixelCount++;\n }\n }\n }\n\n // If significant motion in block, consider it an object\n const motionPercentage = (blockMotion / pixelCount) * 100;\n if (motionPercentage > 30) {\n // 30% of sampled pixels show motion\n objects.push({\n id: `motion-${x}-${y}-${frame.timestamp}`,\n type: \"motion-object\",\n confidence: Math.min(motionPercentage / 100, 1),\n boundingBox: {\n x,\n y,\n width: blockSize,\n height: blockSize,\n },\n });\n }\n }\n }\n\n // Merge adjacent motion blocks into larger objects\n const merged = this.mergeAdjacentObjects(objects);\n\n // Filter out very small objects (likely noise)\n const filtered = merged.filter((obj) => {\n const area = obj.boundingBox.width * obj.boundingBox.height;\n return area > 2000; // Minimum area threshold\n });\n\n return filtered;\n }\n\n private mergeAdjacentObjects(objects: DetectedObject[]): DetectedObject[] {\n if (objects.length === 0) {\n return [];\n }\n\n const merged: DetectedObject[] = [];\n const used = new Set<number>();\n const mergeDistance = 80; // Distance to consider objects adjacent\n\n for (let i = 0; i < objects.length; i++) {\n if (used.has(i)) {\n continue;\n }\n\n const current = objects[i];\n const cluster: DetectedObject[] = [current];\n used.add(i);\n\n // Find all adjacent objects\n let foundNew = true;\n while (foundNew) {\n foundNew = false;\n for (let j = 0; j < objects.length; j++) {\n if (used.has(j)) {\n continue;\n }\n\n const other = objects[j];\n\n // Check if adjacent to any object in cluster\n for (const clusterObj of cluster) {\n const isAdjacent =\n Math.abs(clusterObj.boundingBox.x - other.boundingBox.x) <= mergeDistance &&\n Math.abs(clusterObj.boundingBox.y - other.boundingBox.y) <= mergeDistance;\n\n if (isAdjacent) {\n cluster.push(other);\n used.add(j);\n foundNew = true;\n break;\n }\n }\n }\n }\n\n // Merge cluster into single object\n if (cluster.length > 0) {\n const minX = Math.min(...cluster.map((o) => o.boundingBox.x));\n const minY = Math.min(...cluster.map((o) => o.boundingBox.y));\n const maxX = Math.max(...cluster.map((o) => o.boundingBox.x + o.boundingBox.width));\n const maxY = Math.max(...cluster.map((o) => o.boundingBox.y + o.boundingBox.height));\n const avgConfidence = cluster.reduce((sum, o) => sum + o.confidence, 0) / cluster.length;\n\n merged.push({\n id: `merged-${minX}-${minY}-${Date.now()}`,\n type: this.classifyObjectBySize(maxX - minX, maxY - minY),\n confidence: avgConfidence,\n boundingBox: {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY,\n },\n });\n }\n }\n\n return merged;\n }\n\n private classifyObjectBySize(width: number, height: number): string {\n const area = width * height;\n const aspectRatio = width / height;\n\n // Improved classification heuristics\n if (area > 30000 && aspectRatio > 0.4 && aspectRatio < 0.8) {\n return \"person-candidate\";\n } else if (area > 20000) {\n return \"large-object\";\n } else if (area > 8000) {\n return \"medium-object\";\n } else {\n return \"small-object\";\n }\n }\n\n private async detectPeopleFromMotion(\n frame: VisionFrame,\n objects: DetectedObject[]\n ): Promise<PersonInfo[]> {\n const people: PersonInfo[] = [];\n const personCandidates = objects.filter((o) => o.type === \"person-candidate\");\n\n for (let i = 0; i < personCandidates.length; i++) {\n const candidate = personCandidates[i];\n const box = candidate.boundingBox;\n\n // Simple heuristic: if height > width * 1.5, likely standing\n // if width > height, likely sitting/lying\n const aspectRatio = box.width / box.height;\n let pose: \"standing\" | \"sitting\" | \"lying\" | \"unknown\" = \"unknown\";\n\n if (aspectRatio < 0.6) {\n pose = \"standing\";\n } else if (aspectRatio > 1.2) {\n pose = \"lying\";\n } else {\n pose = \"sitting\";\n }\n\n // Estimate facing based on motion direction (simplified)\n let facing: \"camera\" | \"away\" | \"left\" | \"right\" | \"unknown\" = \"unknown\";\n if (this.lastFrame) {\n // In Phase 1, we'll just use 'unknown' or random assignment\n // Phase 2 will implement proper pose detection\n facing = \"camera\"; // Default assumption\n }\n\n people.push({\n id: `person-${i}-${frame.timestamp}`,\n confidence: candidate.confidence,\n pose,\n facing,\n boundingBox: box,\n });\n }\n\n return people;\n }\n\n private startScreenProcessing(): void {\n if (this.screenProcessingInterval) {\n return;\n }\n\n this.screenProcessingInterval = setInterval(async () => {\n if (!this.isProcessingScreen) {\n this.isProcessingScreen = true;\n try {\n await this.captureAndProcessScreen();\n } catch (error) {\n logger.error(\"[VisionService] Screen processing error:\", error);\n }\n this.isProcessingScreen = false;\n }\n }, this.visionConfig.screenCaptureInterval || 2000);\n\n logger.debug(\"[VisionService] Started screen processing loop\");\n }\n\n private async captureAndProcessScreen(): Promise<void> {\n try {\n // Capture screen\n const capture = await this.screenCapture.captureScreen();\n this.lastScreenCapture = capture;\n\n // Process active tile\n const activeTile = this.screenCapture.getActiveTile();\n if (activeTile?.data) {\n const tileAnalysis = await this.analyzeTile(activeTile);\n activeTile.analysis = tileAnalysis;\n }\n\n // Update enhanced scene description\n await this.updateEnhancedSceneDescription();\n } catch (error) {\n logger.error(\"[VisionService] Error capturing screen:\", error);\n }\n }\n\n private async analyzeTile(tile: ScreenTile): Promise<TileAnalysis> {\n const analysis: TileAnalysis = {\n timestamp: Date.now(),\n };\n\n try {\n // Run Florence-2 analysis if enabled\n if (this.visionConfig.florence2Enabled && tile.data) {\n analysis.florence2 = await this.florence2.analyzeTile(tile);\n analysis.summary = analysis.florence2.caption;\n }\n\n // Run OCR if enabled\n if (this.visionConfig.ocrEnabled && tile.data) {\n analysis.ocr = await this.ocrService.extractFromTile(tile);\n analysis.text = analysis.ocr.fullText;\n }\n\n // Extract objects from Florence-2 results\n if (analysis.florence2?.objects) {\n analysis.objects = analysis.florence2.objects.map((obj) => ({\n id: `screen-obj-${Date.now()}-${Math.random()}`,\n type: obj.label,\n confidence: obj.confidence,\n boundingBox: obj.bbox,\n }));\n }\n } catch (error) {\n logger.error(\"[VisionService] Error analyzing tile:\", error);\n }\n\n return analysis;\n }\n\n private async updateEnhancedSceneDescription(): Promise<void> {\n if (!this.lastScreenCapture) {\n return;\n }\n\n const enhancedScene: EnhancedSceneDescription = {\n ...(this.lastSceneDescription || {\n timestamp: Date.now(),\n description: \"\",\n objects: [],\n people: [],\n sceneChanged: false,\n changePercentage: 0,\n }),\n screenCapture: this.lastScreenCapture,\n screenAnalysis: {\n fullScreenOCR: \"\",\n activeTile: this.screenCapture.getActiveTile()?.analysis,\n gridSummary: \"\",\n focusedApp: \"\",\n uiElements: [],\n },\n };\n\n // Aggregate OCR from all processed tiles\n const processedTiles = this.lastScreenCapture.tiles.filter((t) => t.analysis?.ocr);\n if (processedTiles.length > 0 && enhancedScene.screenAnalysis) {\n enhancedScene.screenAnalysis.fullScreenOCR = processedTiles\n .map((t) => t.analysis?.ocr?.fullText)\n .join(\"\\n\");\n }\n\n // Generate grid summary\n if (this.lastScreenCapture.tiles.length > 0 && enhancedScene.screenAnalysis) {\n const tilesWithContent = this.lastScreenCapture.tiles.filter((t) => t.analysis);\n enhancedScene.screenAnalysis.gridSummary = `Screen divided into ${this.lastScreenCapture.tiles.length} tiles, ${tilesWithContent.length} analyzed`;\n }\n\n // Detect focused application (heuristic based on UI elements)\n if (enhancedScene.screenAnalysis?.activeTile?.florence2?.objects) {\n const windows = enhancedScene.screenAnalysis.activeTile.florence2.objects.filter(\n (obj) => obj.label === \"window\"\n );\n if (windows.length > 0 && enhancedScene.screenAnalysis) {\n enhancedScene.screenAnalysis.focusedApp = \"Desktop Application\";\n }\n }\n\n this.lastEnhancedScene = enhancedScene;\n }\n\n // Public API methods\n\n public async getCurrentFrame(): Promise<VisionFrame | null> {\n return this.lastFrame;\n }\n\n public async getSceneDescription(): Promise<SceneDescription | null> {\n return this.lastSceneDescription;\n }\n\n public async getEnhancedSceneDescription(): Promise<EnhancedSceneDescription | null> {\n // If worker manager is available, use its high-FPS data\n if (this.workerManager) {\n return this.workerManager.getLatestEnhancedScene();\n }\n\n // Otherwise fall back to standard processing\n return this.lastEnhancedScene || this.lastSceneDescription;\n }\n\n public async getScreenCapture(): Promise<ScreenCapture | null> {\n return this.lastScreenCapture;\n }\n\n public getVisionMode(): VisionMode {\n return this.visionConfig.visionMode || VisionMode.CAMERA;\n }\n\n public async setVisionMode(mode: VisionMode): Promise<void> {\n logger.info(\n `[VisionService] Changing vision mode from ${this.visionConfig.visionMode} to ${mode}`\n );\n\n // Stop current processing\n this.stopProcessing();\n\n // Update configuration\n this.visionConfig.visionMode = mode;\n\n // Reinitialize based on new mode\n if (mode === VisionMode.OFF) {\n logger.info(\"[VisionService] Vision disabled\");\n return;\n }\n\n // Initialize components for new mode\n if ((mode === VisionMode.CAMERA || mode === VisionMode.BOTH) && !this.camera) {\n await this.initializeCameraVision();\n }\n\n if (\n (mode === VisionMode.SCREEN || mode === VisionMode.BOTH) &&\n (!this.florence2.isInitialized() || !this.ocrService.isInitialized())\n ) {\n await this.initializeScreenVision();\n }\n\n // Start processing for new mode\n this.startProcessing();\n }\n\n private stopProcessing(): void {\n if (this.frameProcessingInterval) {\n clearInterval(this.frameProcessingInterval);\n this.frameProcessingInterval = null;\n }\n\n if (this.screenProcessingInterval) {\n clearInterval(this.screenProcessingInterval);\n this.screenProcessingInterval = null;\n }\n }\n\n public getCameraInfo(): CameraInfo | null {\n if (!this.camera) {\n return null;\n }\n\n return {\n id: this.camera.id,\n name: this.camera.name,\n connected: true,\n };\n }\n\n public isActive(): boolean {\n return this.camera !== null && this.frameProcessingInterval !== null;\n }\n\n // Helper methods for face recognition\n private calculateBoxOverlap(box1: BoundingBox, box2: BoundingBox): number {\n const x1 = Math.max(box1.x, box2.x);\n const y1 = Math.max(box1.y, box2.y);\n const x2 = Math.min(box1.x + box1.width, box2.x + box2.width);\n const y2 = Math.min(box1.y + box1.height, box2.y + box2.height);\n\n if (x2 < x1 || y2 < y1) {\n return 0;\n }\n\n const intersection = (x2 - x1) * (y2 - y1);\n const area1 = box1.width * box1.height;\n const area2 = box2.width * box2.height;\n const union = area1 + area2 - intersection;\n\n return intersection / union;\n }\n\n private getDominantExpression(expressions: {\n neutral: number;\n happy: number;\n sad: number;\n angry: number;\n fearful: number;\n disgusted: number;\n surprised: number;\n }): string {\n let maxValue = 0;\n let dominantExpression = \"neutral\";\n\n const expressionEntries: [string, number][] = [\n [\"neutral\", expressions.neutral],\n [\"happy\", expressions.happy],\n [\"sad\", expressions.sad],\n [\"angry\", expressions.angry],\n [\"fearful\", expressions.fearful],\n [\"disgusted\", expressions.disgusted],\n [\"surprised\", expressions.surprised],\n ];\n\n for (const [expression, value] of expressionEntries) {\n if (value > maxValue) {\n maxValue = value;\n dominantExpression = expression;\n }\n }\n\n return dominantExpression;\n }\n\n // Public methods for entity tracking\n public getEntityTracker(): EntityTracker {\n return this.entityTracker;\n }\n\n public getFaceRecognition(): FaceRecognition {\n return this.faceRecognition;\n }\n\n async stop(): Promise<void> {\n logger.info(\"[VisionService] Stopping vision service...\");\n\n this.stopProcessing();\n\n if (this.audioCapture) {\n await this.audioCapture.stop();\n this.audioCapture = null;\n }\n\n if (this.streamingAudioCapture) {\n await this.streamingAudioCapture.stop();\n this.streamingAudioCapture = null;\n }\n\n if (this.visionModels) {\n await this.visionModels.dispose();\n }\n\n if (this.workerManager) {\n await this.workerManager.stop();\n this.workerManager = null;\n }\n\n this.camera = null;\n this.lastFrame = null;\n this.lastSceneDescription = null;\n this.lastScreenCapture = null;\n this.lastEnhancedScene = null;\n this.isProcessing = false;\n this.isProcessingScreen = false;\n\n // Dispose of models\n await this.florence2.dispose();\n await this.ocrService.dispose();\n\n logger.info(\"[VisionService] Stopped.\");\n }\n\n private async findCamera(): Promise<CameraDevice | null> {\n try {\n // Get list of available cameras\n const cameras = await this.listCameras();\n\n if (cameras.length === 0) {\n logger.warn(\"[VisionService] No cameras detected\");\n return null;\n }\n\n // If camera name is specified, try to find it\n if (this.visionConfig.cameraName) {\n const searchName = this.visionConfig.cameraName.toLowerCase();\n const matchedCamera = cameras.find((cam) => cam.name.toLowerCase().includes(searchName));\n\n if (matchedCamera) {\n return this.createCameraDevice(matchedCamera);\n }\n\n logger.warn(\n `[VisionService] Camera \"${this.visionConfig.cameraName}\" not found, using default`\n );\n }\n\n // Use first available camera\n return this.createCameraDevice(cameras[0]);\n } catch (error) {\n logger.error(\"[VisionService] Error finding camera:\", error);\n return null;\n }\n }\n\n private async listCameras(): Promise<CameraInfo[]> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // macOS: Use system_profiler\n const { stdout } = await execAsync(\"system_profiler SPCameraDataType -json\");\n const data = JSON.parse(stdout);\n const cameras: CameraInfo[] = [];\n\n if (data.SPCameraDataType && Array.isArray(data.SPCameraDataType)) {\n for (const camera of data.SPCameraDataType) {\n cameras.push({\n id: camera.unique_id || camera._name,\n name: camera._name,\n connected: true,\n });\n }\n }\n\n return cameras;\n } else if (platform === \"linux\") {\n // Linux: Use v4l2\n const { stdout } = await execAsync(\"v4l2-ctl --list-devices\");\n const cameras: CameraInfo[] = [];\n const lines = stdout.split(\"\\n\");\n\n let currentName = \"\";\n for (const line of lines) {\n if (line && !line.startsWith(\"\\t\")) {\n currentName = line.replace(\":\", \"\").trim();\n } else if (line.trim().startsWith(\"/dev/video\")) {\n const devicePath = line.trim();\n const id = devicePath.replace(\"/dev/video\", \"\");\n cameras.push({\n id,\n name: currentName,\n connected: true,\n });\n }\n }\n\n return cameras;\n } else if (platform === \"win32\") {\n // Windows: Use PowerShell\n const { stdout } = await execAsync(\n 'powershell -Command \"Get-PnpDevice -Class Camera | Select-Object FriendlyName, InstanceId | ConvertTo-Json\"'\n );\n const devices = JSON.parse(stdout);\n const cameras: CameraInfo[] = [];\n\n if (Array.isArray(devices)) {\n for (const device of devices) {\n cameras.push({\n id: device.InstanceId,\n name: device.FriendlyName,\n connected: true,\n });\n }\n }\n\n return cameras;\n }\n\n return [];\n } catch (error) {\n logger.error(\"[VisionService] Error listing cameras:\", error);\n return [];\n }\n }\n\n private createCameraDevice(info: CameraInfo): CameraDevice {\n const platform = process.platform;\n\n return {\n id: info.id,\n name: info.name,\n capture: async () => {\n const tempFile = path.join(process.cwd(), `temp_capture_${Date.now()}.jpg`);\n\n try {\n if (platform === \"darwin\") {\n // macOS: Use imagesnap\n try {\n await execAsync(`imagesnap -d \"${info.name}\" \"${tempFile}\"`);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (errorMessage.includes(\"command not found\")) {\n throw new Error(\"imagesnap not installed. Run: brew install imagesnap\");\n }\n throw error;\n }\n } else if (platform === \"linux\") {\n // Linux: Use fswebcam\n try {\n await execAsync(\n `fswebcam -d /dev/video${info.id} -r 1280x720 --jpeg 85 \"${tempFile}\"`\n );\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (errorMessage.includes(\"command not found\")) {\n throw new Error(\"fswebcam not installed. Run: sudo apt-get install fswebcam\");\n }\n throw error;\n }\n } else if (platform === \"win32\") {\n // Windows: Use DirectShow via ffmpeg\n try {\n await execAsync(\n `ffmpeg -f dshow -i video=\"${info.name}\" -frames:v 1 -q:v 2 \"${tempFile}\" -y`\n );\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (errorMessage.includes(\"not recognized\") || errorMessage.includes(\"not found\")) {\n throw new Error(\"ffmpeg not installed. Download from ffmpeg.org and add to PATH\");\n }\n throw error;\n }\n } else {\n throw new Error(`Unsupported platform: ${platform}`);\n }\n\n // Read the captured image\n const imageBuffer = await fs.readFile(tempFile);\n\n // Clean up temp file\n await fs.unlink(tempFile).catch(() => {});\n\n return imageBuffer;\n } catch (error) {\n // Clean up temp file on error\n await fs.unlink(tempFile).catch(() => {});\n throw error;\n }\n },\n };\n }\n\n public async captureImage(): Promise<Buffer | null> {\n if (!this.camera) {\n logger.warn(\"[VisionService] No camera available for capture\");\n return null;\n }\n\n try {\n return await this.camera.capture();\n } catch (error) {\n logger.error(\"[VisionService] Failed to capture image:\", error);\n return null;\n }\n }\n}\n",
9
- "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 { type IAgentRuntime, logger, ModelType } from \"@elizaos/core\";\n\nconst execAsync = promisify(exec);\n\nexport interface AudioConfig {\n enabled: boolean;\n transcriptionInterval: number; // milliseconds\n device?: string;\n sampleRate?: number;\n channels?: number;\n}\n\nexport class AudioCaptureService {\n private runtime: IAgentRuntime;\n private config: AudioConfig;\n private isRecording = false;\n private recordingInterval: NodeJS.Timeout | null = null;\n\n constructor(runtime: IAgentRuntime, config: AudioConfig) {\n this.runtime = runtime;\n this.config = {\n sampleRate: 16000,\n channels: 1,\n ...config,\n };\n }\n\n async initialize(): Promise<void> {\n if (!this.config.enabled) {\n logger.info(\"[AudioCapture] Audio capture disabled\");\n return;\n }\n\n try {\n logger.info(\"[AudioCapture] Initializing audio capture...\");\n\n // Check for audio recording tools\n const tool = await this.checkAudioTools();\n if (!tool.available) {\n throw new Error(`Audio recording tool not available. ${tool.message}`);\n }\n\n logger.info(`[AudioCapture] Using ${tool.tool} for audio capture`);\n logger.info(`[AudioCapture] Transcription interval: ${this.config.transcriptionInterval}ms`);\n\n // Start recording loop if interval is set\n if (this.config.transcriptionInterval > 0) {\n this.startTranscriptionLoop();\n }\n\n logger.info(\"[AudioCapture] Audio capture initialized\");\n } catch (error) {\n logger.error(\"[AudioCapture] Failed to initialize:\", error);\n throw error;\n }\n }\n\n private async checkAudioTools(): Promise<{ available: boolean; tool: string; message?: string }> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // macOS: Use sox\n await execAsync(\"which sox\");\n return { available: true, tool: \"sox\" };\n } else if (platform === \"linux\") {\n // Linux: Use arecord (ALSA)\n await execAsync(\"which arecord\");\n return { available: true, tool: \"arecord\" };\n } else if (platform === \"win32\") {\n // Windows: Use ffmpeg\n await execAsync(\"where ffmpeg\");\n return { available: true, tool: \"ffmpeg\" };\n }\n return { available: false, tool: \"none\", message: \"Unsupported platform\" };\n } catch (_error) {\n // Tool not found\n const toolName = platform === \"darwin\" ? \"sox\" : platform === \"linux\" ? \"arecord\" : \"ffmpeg\";\n const installCmd =\n platform === \"darwin\"\n ? \"brew install sox\"\n : platform === \"linux\"\n ? \"sudo apt-get install alsa-utils\"\n : \"Download ffmpeg from ffmpeg.org\";\n return {\n available: false,\n tool: toolName,\n message: `Install with: ${installCmd}`,\n };\n }\n }\n\n private startTranscriptionLoop(): void {\n if (this.recordingInterval) {\n return;\n }\n\n // Start continuous recording with periodic transcription\n this.recordingInterval = setInterval(async () => {\n if (!this.isRecording) {\n await this.recordAndTranscribe();\n }\n }, this.config.transcriptionInterval);\n\n logger.info(\"[AudioCapture] Started transcription loop\");\n }\n\n async recordAndTranscribe(): Promise<string | null> {\n if (this.isRecording) {\n logger.warn(\"[AudioCapture] Already recording\");\n return null;\n }\n\n this.isRecording = true;\n const audioFile = path.join(process.cwd(), `audio_${Date.now()}.wav`);\n\n try {\n logger.debug(\"[AudioCapture] Starting audio recording...\");\n\n // Record audio for the specified duration\n await this.recordAudio(audioFile, this.config.transcriptionInterval / 1000);\n\n logger.debug(\"[AudioCapture] Recording complete, transcribing...\");\n\n // Transcribe using runtime model\n const audioBuffer = await fs.readFile(audioFile);\n const transcription = await this.runtime.useModel(ModelType.TRANSCRIPTION, audioBuffer);\n\n // Clean up audio file\n await fs.unlink(audioFile).catch(() => {});\n\n if (transcription && typeof transcription === \"string\" && transcription.trim()) {\n logger.info(`[AudioCapture] Transcribed: \"${transcription}\"`);\n\n // Create a memory of what was heard\n await this.createAudioMemory(transcription);\n\n return transcription;\n }\n\n return null;\n } catch (error) {\n logger.error(\"[AudioCapture] Recording/transcription failed:\", error);\n await fs.unlink(audioFile).catch(() => {});\n return null;\n } finally {\n this.isRecording = false;\n }\n }\n\n private async recordAudio(outputPath: string, duration: number): Promise<void> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // macOS: Use sox\n const _device = this.config.device || \"default\";\n await execAsync(\n `sox -d -r ${this.config.sampleRate} -c ${this.config.channels} -b 16 \"${outputPath}\" trim 0 ${duration}`\n );\n } else if (platform === \"linux\") {\n // Linux: Use arecord\n const device = this.config.device || \"default\";\n await execAsync(\n `arecord -D ${device} -f S16_LE -r ${this.config.sampleRate} -c ${this.config.channels} -d ${duration} \"${outputPath}\"`\n );\n } else if (platform === \"win32\") {\n // Windows: Use ffmpeg with DirectShow\n const device = this.config.device || \"Microphone\";\n await execAsync(\n `ffmpeg -f dshow -i audio=\"${device}\" -t ${duration} -acodec pcm_s16le -ar ${this.config.sampleRate} -ac ${this.config.channels} \"${outputPath}\" -y`\n );\n } else {\n throw new Error(`Unsupported platform: ${platform}`);\n }\n } catch (error: unknown) {\n logger.error(\n \"[AudioCapture] Audio recording failed:\",\n error instanceof Error ? error.message : String(error)\n );\n throw error;\n }\n }\n\n private async createAudioMemory(transcription: string): Promise<void> {\n try {\n const _memory = {\n content: {\n text: `[Audio Transcription] ${transcription}`,\n type: \"audio_transcription\",\n source: \"microphone\",\n timestamp: Date.now(),\n },\n metadata: {\n isAudioTranscription: true,\n duration: this.config.transcriptionInterval,\n },\n };\n\n // Store in agent's context\n // createMemory requires runtime-specific database adapter implementation\n logger.info(\"[AudioCapture] Audio transcription stored in context\");\n } catch (error) {\n logger.error(\"[AudioCapture] Failed to create audio memory:\", error);\n }\n }\n\n async listAudioDevices(): Promise<string[]> {\n const platform = process.platform;\n const devices: string[] = [];\n\n try {\n if (platform === \"darwin\") {\n // macOS: List audio devices using system_profiler\n const { stdout } = await execAsync(\"system_profiler SPAudioDataType -json\");\n const data = JSON.parse(stdout);\n\n if (data.SPAudioDataType) {\n for (const device of data.SPAudioDataType) {\n if (device._name?.includes(\"Input\")) {\n devices.push(device._name);\n }\n }\n }\n } else if (platform === \"linux\") {\n // Linux: List ALSA devices\n const { stdout } = await execAsync(\"arecord -l\");\n const lines = stdout.split(\"\\n\");\n\n for (const line of lines) {\n if (line.includes(\"card\")) {\n const match = line.match(/card (\\d+):.*\\[(.*?)\\]/);\n if (match) {\n devices.push(`hw:${match[1]}`);\n }\n }\n }\n } else if (platform === \"win32\") {\n // Windows: List audio devices using ffmpeg\n try {\n const { stdout } = await execAsync(\"ffmpeg -list_devices true -f dshow -i dummy 2>&1\");\n const lines = stdout.split(\"\\n\");\n let isAudioSection = false;\n\n for (const line of lines) {\n if (line.includes(\"DirectShow audio devices\")) {\n isAudioSection = true;\n } else if (isAudioSection && line.includes('\"')) {\n const match = line.match(/\"([^\"]+)\"/);\n if (match) {\n devices.push(match[1]);\n }\n }\n }\n } catch (_error) {\n // ffmpeg returns non-zero exit code when listing devices\n // but we can still parse the output\n }\n }\n } catch (error) {\n logger.error(\"[AudioCapture] Failed to list audio devices:\", error);\n }\n\n return devices;\n }\n\n isActive(): boolean {\n return this.config.enabled && this.recordingInterval !== null;\n }\n\n async stop(): Promise<void> {\n logger.info(\"[AudioCapture] Stopping audio capture...\");\n\n if (this.recordingInterval) {\n clearInterval(this.recordingInterval);\n this.recordingInterval = null;\n }\n\n // Wait for any ongoing recording to complete\n while (this.isRecording) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n logger.info(\"[AudioCapture] Audio capture stopped\");\n }\n}\n",
10
- "import { type ChildProcess, spawn } from \"node:child_process\";\nimport { EventEmitter } from \"node:events\";\nimport { type IAgentRuntime, logger, ModelType } from \"@elizaos/core\";\n\nexport interface StreamingAudioConfig {\n enabled: boolean;\n device?: string;\n sampleRate?: number;\n channels?: number;\n vadThreshold?: number; // 0-1, energy threshold for speech detection\n silenceTimeout?: number; // ms to wait before considering speech ended\n responseDelay?: number; // ms to wait before processing (for interruption detection)\n chunkSize?: number; // bytes per chunk for streaming\n}\n\ninterface AudioChunk {\n data: Buffer;\n timestamp: number;\n energy: number;\n}\n\nexport class StreamingAudioCaptureService extends EventEmitter {\n private runtime: IAgentRuntime;\n private config: StreamingAudioConfig;\n private captureProcess: ChildProcess | null = null;\n private isCapturing = false;\n private audioBuffer: AudioChunk[] = [];\n private isSpeaking = false;\n private silenceTimer: NodeJS.Timeout | null = null;\n private transcriptionInProgress = false;\n private currentTranscription = \"\";\n private responseTimer: NodeJS.Timeout | null = null;\n\n constructor(runtime: IAgentRuntime, config: StreamingAudioConfig) {\n super();\n this.runtime = runtime;\n this.config = {\n sampleRate: 16000,\n channels: 1,\n vadThreshold: 0.01,\n silenceTimeout: 1500, // 1.5 seconds of silence to end speech\n responseDelay: 3000, // 3 seconds before response (allows for interruption)\n chunkSize: 4096,\n ...config,\n };\n }\n\n async initialize(): Promise<void> {\n if (!this.config.enabled) {\n logger.info(\"[StreamingAudio] Audio capture disabled\");\n return;\n }\n\n try {\n logger.info(\"[StreamingAudio] Initializing streaming audio capture...\");\n\n // Start continuous audio capture\n await this.startContinuousCapture();\n\n logger.info(\"[StreamingAudio] Streaming audio capture initialized\");\n } catch (error) {\n logger.error(\"[StreamingAudio] Failed to initialize:\", error);\n throw error;\n }\n }\n\n private async startContinuousCapture(): Promise<void> {\n const platform = process.platform;\n let command: string;\n let args: string[];\n\n if (platform === \"darwin\") {\n // macOS: Use sox for continuous capture\n command = \"sox\";\n args = [\n \"-d\", // default input device\n \"-r\",\n this.config.sampleRate?.toString(),\n \"-c\",\n this.config.channels?.toString(),\n \"-b\",\n \"16\",\n \"-e\",\n \"signed\",\n \"-t\",\n \"raw\",\n \"-\", // output to stdout\n ];\n } else if (platform === \"linux\") {\n // Linux: Use arecord\n command = \"arecord\";\n args = [\n \"-D\",\n this.config.device || \"default\",\n \"-f\",\n \"S16_LE\",\n \"-r\",\n this.config.sampleRate?.toString(),\n \"-c\",\n this.config.channels?.toString(),\n \"-t\",\n \"raw\",\n \"-\", // output to stdout\n ];\n } else if (platform === \"win32\") {\n // Windows: Use ffmpeg\n command = \"ffmpeg\";\n args = [\n \"-f\",\n \"dshow\",\n \"-i\",\n `audio=\"${this.config.device || \"Microphone\"}\"`,\n \"-acodec\",\n \"pcm_s16le\",\n \"-ar\",\n this.config.sampleRate?.toString(),\n \"-ac\",\n this.config.channels?.toString(),\n \"-f\",\n \"s16le\",\n \"pipe:1\", // output to stdout\n ];\n } else {\n throw new Error(`Unsupported platform: ${platform}`);\n }\n\n this.captureProcess = spawn(command, args);\n this.isCapturing = true;\n\n // Handle audio data stream\n this.captureProcess.stdout?.on(\"data\", (chunk: Buffer) => {\n this.processAudioChunk(chunk);\n });\n\n this.captureProcess.stderr?.on(\"data\", (data) => {\n logger.debug(\"[StreamingAudio] Capture stderr:\", data.toString());\n });\n\n this.captureProcess.on(\"error\", (error) => {\n logger.error(\n \"[StreamingAudio] Capture process error:\",\n error instanceof Error ? error.message : String(error)\n );\n this.isCapturing = false;\n });\n\n this.captureProcess.on(\"exit\", (code) => {\n logger.info(\"[StreamingAudio] Capture process exited with code:\", String(code ?? 0));\n this.isCapturing = false;\n });\n }\n\n private processAudioChunk(chunk: Buffer): void {\n // Calculate audio energy for VAD\n const energy = this.calculateEnergy(chunk);\n const timestamp = Date.now();\n\n // Store chunk\n const audioChunk: AudioChunk = { data: chunk, timestamp, energy };\n\n // Voice Activity Detection\n if (energy > (this.config.vadThreshold ?? 0.01)) {\n if (!this.isSpeaking) {\n // Speech started\n this.isSpeaking = true;\n logger.debug(\"[StreamingAudio] Speech detected, starting recording\");\n this.emit(\"speechStart\");\n\n // Clear any pending response\n if (this.responseTimer) {\n clearTimeout(this.responseTimer);\n this.responseTimer = null;\n logger.debug(\"[StreamingAudio] Cancelled pending response due to new speech\");\n }\n }\n\n // Add to buffer\n this.audioBuffer.push(audioChunk);\n\n // Reset silence timer\n if (this.silenceTimer) {\n clearTimeout(this.silenceTimer);\n }\n\n // Start streaming transcription if not already running\n if (!this.transcriptionInProgress) {\n this.startStreamingTranscription();\n }\n } else if (this.isSpeaking) {\n // Currently in speech but detected silence\n this.audioBuffer.push(audioChunk);\n\n // Set timer for end of speech\n if (!this.silenceTimer) {\n this.silenceTimer = setTimeout(() => {\n this.endSpeech();\n }, this.config.silenceTimeout ?? 1500);\n }\n }\n\n // Clean up old chunks (keep last 30 seconds)\n const cutoffTime = timestamp - 30000;\n this.audioBuffer = this.audioBuffer.filter((c) => c.timestamp > cutoffTime);\n }\n\n private calculateEnergy(chunk: Buffer): number {\n // Calculate RMS energy of audio chunk\n let sum = 0;\n const samples = chunk.length / 2; // 16-bit samples\n\n for (let i = 0; i < chunk.length; i += 2) {\n const sample = chunk.readInt16LE(i);\n sum += sample * sample;\n }\n\n const rms = Math.sqrt(sum / samples);\n return rms / 32768; // Normalize to 0-1\n }\n\n private async startStreamingTranscription(): Promise<void> {\n if (this.transcriptionInProgress) {\n return;\n }\n\n this.transcriptionInProgress = true;\n logger.debug(\"[StreamingAudio] Starting streaming transcription\");\n\n try {\n // Get audio data from buffer\n const audioData = this.getRecentAudioData();\n\n if (audioData.length === 0) {\n this.transcriptionInProgress = false;\n return;\n }\n\n // Use streaming transcription if available, otherwise batch\n const result = await this.transcribeAudio(audioData);\n\n if (result?.trim()) {\n this.currentTranscription = result;\n logger.info(`[StreamingAudio] Partial transcription: \"${result}\"`);\n this.emit(\"transcription\", { text: result, isFinal: false });\n }\n } catch (error) {\n logger.error(\"[StreamingAudio] Transcription error:\", error);\n }\n\n this.transcriptionInProgress = false;\n\n // Continue transcription if still speaking\n if (this.isSpeaking) {\n setTimeout(() => this.startStreamingTranscription(), 500);\n }\n }\n\n private endSpeech(): void {\n if (!this.isSpeaking) {\n return;\n }\n\n this.isSpeaking = false;\n this.silenceTimer = null;\n logger.debug(\"[StreamingAudio] Speech ended\");\n this.emit(\"speechEnd\");\n\n // Get final transcription\n this.processFinalTranscription();\n }\n\n private async processFinalTranscription(): Promise<void> {\n const audioData = this.getRecentAudioData();\n\n if (audioData.length === 0) {\n return;\n }\n\n try {\n // Get final transcription\n const finalText = await this.transcribeAudio(audioData);\n\n if (finalText?.trim()) {\n this.currentTranscription = finalText;\n logger.info(`[StreamingAudio] Final transcription: \"${finalText}\"`);\n this.emit(\"transcription\", { text: finalText, isFinal: true });\n\n // Set timer for response generation\n this.responseTimer = setTimeout(() => {\n this.generateResponse(finalText);\n }, this.config.responseDelay ?? 3000);\n }\n } catch (error) {\n logger.error(\"[StreamingAudio] Final transcription error:\", error);\n } finally {\n // Clear audio buffer\n this.audioBuffer = [];\n this.currentTranscription = \"\";\n }\n }\n\n private getRecentAudioData(): Buffer {\n if (this.audioBuffer.length === 0) {\n return Buffer.alloc(0);\n }\n\n // Get audio from start of speech to now\n const startTime = this.audioBuffer[0].timestamp;\n const relevantChunks = this.audioBuffer.filter((c) => c.timestamp >= startTime);\n\n // Combine chunks\n const totalLength = relevantChunks.reduce((sum, c) => sum + c.data.length, 0);\n const combined = Buffer.alloc(totalLength);\n let offset = 0;\n\n for (const chunk of relevantChunks) {\n chunk.data.copy(combined, offset);\n offset += chunk.data.length;\n }\n\n return combined;\n }\n\n private async transcribeAudio(audioData: Buffer): Promise<string | null> {\n try {\n // Convert raw audio to WAV format\n const wavBuffer = this.rawToWav(audioData);\n\n // Use runtime transcription model\n const result = await this.runtime.useModel(ModelType.TRANSCRIPTION, wavBuffer);\n\n return result as string;\n } catch (error) {\n logger.error(\"[StreamingAudio] Transcription failed:\", error);\n return null;\n }\n }\n\n private rawToWav(rawData: Buffer): Buffer {\n // Create WAV header\n const sampleRate = this.config.sampleRate ?? 16000;\n const channels = this.config.channels ?? 1;\n const bitsPerSample = 16;\n const byteRate = sampleRate * channels * (bitsPerSample / 8);\n const blockAlign = channels * (bitsPerSample / 8);\n const dataSize = rawData.length;\n const fileSize = 36 + dataSize;\n\n const header = Buffer.alloc(44);\n\n // RIFF chunk\n header.write(\"RIFF\", 0);\n header.writeUInt32LE(fileSize, 4);\n header.write(\"WAVE\", 8);\n\n // fmt chunk\n header.write(\"fmt \", 12);\n header.writeUInt32LE(16, 16); // fmt chunk size\n header.writeUInt16LE(1, 20); // PCM format\n header.writeUInt16LE(channels, 22);\n header.writeUInt32LE(sampleRate, 24);\n header.writeUInt32LE(byteRate, 28);\n header.writeUInt16LE(blockAlign, 32);\n header.writeUInt16LE(bitsPerSample, 34);\n\n // data chunk\n header.write(\"data\", 36);\n header.writeUInt32LE(dataSize, 40);\n\n return Buffer.concat([header, rawData]);\n }\n\n private async generateResponse(transcription: string): Promise<void> {\n this.responseTimer = null;\n\n try {\n // Create audio memory\n await this.createAudioMemory(transcription);\n\n // Emit event for response generation\n this.emit(\"utteranceComplete\", transcription);\n } catch (error) {\n logger.error(\"[StreamingAudio] Response generation error:\", error);\n }\n }\n\n private async createAudioMemory(transcription: string): Promise<void> {\n try {\n const _memory = {\n content: {\n text: `[Audio] ${transcription}`,\n type: \"audio_transcription\",\n source: \"microphone_streaming\",\n timestamp: Date.now(),\n },\n metadata: {\n isAudioTranscription: true,\n streaming: true,\n },\n };\n\n logger.info(\"[StreamingAudio] Audio transcription stored in context\");\n } catch (error) {\n logger.error(\"[StreamingAudio] Failed to create audio memory:\", error);\n }\n }\n\n async stop(): Promise<void> {\n logger.info(\"[StreamingAudio] Stopping audio capture...\");\n\n if (this.captureProcess) {\n this.captureProcess.kill();\n this.captureProcess = null;\n }\n\n if (this.silenceTimer) {\n clearTimeout(this.silenceTimer);\n this.silenceTimer = null;\n }\n\n if (this.responseTimer) {\n clearTimeout(this.responseTimer);\n this.responseTimer = null;\n }\n\n this.isCapturing = false;\n this.isSpeaking = false;\n this.audioBuffer = [];\n\n logger.info(\"[StreamingAudio] Audio capture stopped\");\n }\n\n isActive(): boolean {\n return this.isCapturing;\n }\n\n getCurrentTranscription(): string {\n return this.currentTranscription;\n }\n\n isSpeechActive(): boolean {\n return this.isSpeaking;\n }\n}\n",
11
- "import { type IAgentRuntime, createUniqueUuid, logger, type UUID } from \"@elizaos/core\";\nimport type { BoundingBox, DetectedObject, PersonInfo, TrackedEntity, WorldState } 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((center1.x - center2.x) ** 2 + (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 // Sync detected entities with the runtime's entity system\n for (const entity of frameEntities) {\n // Convert the human-readable tracker ID (e.g. \"person-123-abc\") to a\n // deterministic UUID that PostgreSQL accepts. The same local ID always\n // maps to the same UUID for a given agent, so updates stay consistent.\n const entityUuid = createUniqueUuid(runtime, entity.id);\n\n const elizaEntity = {\n id: entityUuid,\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 try {\n const existing = await runtime.getEntityById(entityUuid);\n if (!existing) {\n await runtime.createEntity(elizaEntity);\n logger.debug(`[EntityTracker] Created entity ${entity.id} (${entityUuid}) in runtime`);\n } else {\n await runtime.updateEntity({\n ...elizaEntity,\n id: entityUuid,\n });\n logger.debug(`[EntityTracker] Updated entity ${entity.id} (${entityUuid}) in runtime`);\n }\n } catch (err) {\n logger.debug(\n `[EntityTracker] Could not sync entity ${entity.id}: ${err instanceof Error ? err.message : String(err)}`\n );\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",
12
- "import * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { logger } from \"@elizaos/core\";\nimport * as faceapi from \"face-api.js\";\nimport type { FaceLibrary, FaceProfile } from \"./types\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Dynamic imports for optional dependencies\n// Canvas package types differ from DOM types but are runtime-compatible with face-api.js\nlet CanvasModule: typeof import(\"canvas\") | undefined;\n\n/**\n * Type helpers for node-canvas to face-api.js compatibility.\n * The canvas package provides Node.js implementations that are runtime-compatible\n * with face-api.js, but have different TypeScript types than DOM equivalents.\n */\ntype FaceApiEnv = {\n Canvas: typeof HTMLCanvasElement;\n Image: typeof HTMLImageElement;\n ImageData: typeof ImageData;\n};\n\n/**\n * Adapter type for node-canvas Canvas to HTMLCanvasElement.\n * Runtime-compatible but TypeScript types differ.\n */\ntype CanvasAdapter = import(\"canvas\").Canvas & HTMLCanvasElement;\n\nfunction asCanvasEnv(canvas: typeof import(\"canvas\")): FaceApiEnv {\n return {\n // node-canvas types don't match DOM types but are runtime-compatible with face-api.js\n Canvas: canvas.Canvas as unknown as typeof HTMLCanvasElement,\n Image: canvas.Image as unknown as typeof HTMLImageElement,\n ImageData: canvas.ImageData as typeof ImageData,\n };\n}\n\nfunction asHTMLCanvasElement(canvas: import(\"canvas\").Canvas): HTMLCanvasElement {\n // node-canvas Canvas is runtime-compatible with HTMLCanvasElement\n return canvas as CanvasAdapter as HTMLCanvasElement;\n}\n\nasync function initializeCanvas() {\n try {\n CanvasModule = await import(\"canvas\");\n\n // Polyfill for face-api.js - node-canvas is runtime-compatible with face-api.js\n faceapi.env.monkeyPatch(asCanvasEnv(CanvasModule));\n } catch (error) {\n logger.error(\"[FaceRecognition] Canvas module not available:\", error);\n throw new Error(\n \"Canvas module is required for face recognition. Install with: npm install canvas\"\n );\n }\n}\n\nexport class FaceRecognition {\n private initialized = false;\n private faceLibrary: FaceLibrary = {\n faces: new Map(),\n embeddings: new Map(),\n };\n private modelPath = path.join(__dirname, \"..\", \"models\", \"face-api\");\n\n // Thresholds\n private readonly FACE_MATCH_THRESHOLD = 0.6; // Euclidean distance threshold\n private readonly MIN_FACE_SIZE = 50; // Minimum face size in pixels\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n try {\n logger.info(\"[FaceRecognition] Loading face detection models...\");\n\n // Initialize canvas first\n await initializeCanvas();\n\n // Load face-api.js models\n await faceapi.nets.ssdMobilenetv1.loadFromDisk(this.modelPath);\n await faceapi.nets.faceLandmark68Net.loadFromDisk(this.modelPath);\n await faceapi.nets.faceRecognitionNet.loadFromDisk(this.modelPath);\n await faceapi.nets.faceExpressionNet.loadFromDisk(this.modelPath);\n await faceapi.nets.ageGenderNet.loadFromDisk(this.modelPath);\n\n this.initialized = true;\n logger.info(\"[FaceRecognition] Models loaded successfully\");\n } catch (error) {\n logger.error(\"[FaceRecognition] Failed to load models:\", error);\n logger.info(\n \"[FaceRecognition] Download models from: https://github.com/justadudewhohacks/face-api.js-models\"\n );\n throw error;\n }\n }\n\n async detectFaces(\n imageData: Buffer,\n width: number,\n height: number\n ): Promise<\n Array<{\n detection: faceapi.FaceDetection;\n landmarks: faceapi.FaceLandmarks68;\n descriptor: Float32Array;\n expressions: faceapi.FaceExpressions;\n ageGender?: { age: number; gender: string; genderProbability: number };\n }>\n > {\n if (!this.initialized) {\n await this.initialize();\n }\n\n // Validate input parameters\n if (!imageData || imageData.length === 0 || width <= 0 || height <= 0) {\n logger.warn(\n `[FaceRecognition] Invalid input parameters: dataLength=${imageData?.length || 0}, width=${width}, height=${height}`\n );\n return [];\n }\n\n // Validate that the buffer size matches expected dimensions\n const expectedSize = width * height * 4; // RGBA\n if (imageData.length !== expectedSize) {\n logger.warn(\n `[FaceRecognition] Buffer size mismatch: expected=${expectedSize}, actual=${imageData.length}, width=${width}, height=${height}`\n );\n return [];\n }\n\n try {\n if (!CanvasModule) {\n throw new Error(\"Canvas module not initialized. Call initialize() first.\");\n }\n // Create canvas from image data\n const canvas = new CanvasModule.Canvas(width, height);\n const ctx = canvas.getContext(\"2d\");\n const imageDataObj = new CanvasModule.ImageData(\n new Uint8ClampedArray(imageData),\n width,\n height\n );\n ctx.putImageData(imageDataObj, 0, 0);\n\n // Detect faces with full analysis\n // face-api.js accepts HTMLCanvasElement or compatible canvas (node-canvas works)\n const detections = await faceapi\n .detectAllFaces(\n asHTMLCanvasElement(canvas),\n new faceapi.SsdMobilenetv1Options({\n minConfidence: 0.5,\n maxResults: 10,\n })\n )\n .withFaceLandmarks()\n .withFaceDescriptors()\n .withFaceExpressions()\n .withAgeAndGender();\n\n return detections.filter(\n (d: {\n detection: {\n box: {\n width: number;\n height: number;\n };\n };\n }) => {\n const box = d.detection.box;\n return box.width >= this.MIN_FACE_SIZE && box.height >= this.MIN_FACE_SIZE;\n }\n );\n } catch (error) {\n logger.error(\"[FaceRecognition] Face detection failed:\", error);\n return [];\n }\n }\n\n async recognizeFace(\n descriptor: Float32Array\n ): Promise<{ profileId: string; distance: number } | null> {\n let bestMatch: { profileId: string; distance: number } | null = null;\n let minDistance = Infinity;\n\n // Compare with all known faces\n for (const [profileId, embeddings] of this.faceLibrary.embeddings) {\n for (const knownEmbedding of embeddings) {\n const distance = this.euclideanDistance(descriptor, knownEmbedding);\n\n if (distance < this.FACE_MATCH_THRESHOLD && distance < minDistance) {\n minDistance = distance;\n bestMatch = { profileId, distance };\n }\n }\n }\n\n return bestMatch;\n }\n\n async addOrUpdateFace(\n descriptor: Float32Array,\n attributes?: Partial<FaceProfile>\n ): Promise<string> {\n // Check if this face already exists\n const match = await this.recognizeFace(descriptor);\n\n if (match) {\n // Update existing profile\n const profile = this.faceLibrary.faces.get(match.profileId);\n if (!profile) {\n throw new Error(`Profile not found for matched profileId: ${match.profileId}`);\n }\n profile.lastSeen = Date.now();\n profile.seenCount++;\n\n // Add new embedding for better recognition\n const embeddings = this.faceLibrary.embeddings.get(match.profileId);\n if (!embeddings) {\n throw new Error(`Embeddings not found for matched profileId: ${match.profileId}`);\n }\n if (embeddings.length < 10) {\n // Keep up to 10 embeddings per person\n embeddings.push(Array.from(descriptor));\n }\n\n // Update attributes if provided\n if (attributes) {\n Object.assign(profile, attributes);\n }\n\n return match.profileId;\n } else {\n // Create new profile\n const profileId = `face-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n const profile: FaceProfile = {\n id: profileId,\n embeddings: [Array.from(descriptor)],\n firstSeen: Date.now(),\n lastSeen: Date.now(),\n seenCount: 1,\n ...attributes,\n };\n\n this.faceLibrary.faces.set(profileId, profile);\n this.faceLibrary.embeddings.set(profileId, [Array.from(descriptor)]);\n\n logger.info(`[FaceRecognition] New face registered: ${profileId}`);\n return profileId;\n }\n }\n\n getFaceProfile(profileId: string): FaceProfile | undefined {\n return this.faceLibrary.faces.get(profileId);\n }\n\n getAllProfiles(): FaceProfile[] {\n return Array.from(this.faceLibrary.faces.values());\n }\n\n private euclideanDistance(a: Float32Array | number[], b: number[]): number {\n let sum = 0;\n const aArray = Array.from(a);\n for (let i = 0; i < aArray.length; i++) {\n sum += (aArray[i] - b[i]) ** 2;\n }\n return Math.sqrt(sum);\n }\n\n // Persistence methods\n async saveFaceLibrary(path: string): Promise<void> {\n const data = {\n faces: Array.from(this.faceLibrary.faces.entries()),\n embeddings: Array.from(this.faceLibrary.embeddings.entries()),\n };\n\n const fs = await import(\"node:fs/promises\");\n await fs.writeFile(path, JSON.stringify(data, null, 2));\n logger.info(`[FaceRecognition] Face library saved to ${path}`);\n }\n\n async loadFaceLibrary(path: string): Promise<void> {\n try {\n const fs = await import(\"node:fs/promises\");\n const data = JSON.parse(await fs.readFile(path, \"utf-8\"));\n\n this.faceLibrary.faces = new Map(data.faces);\n this.faceLibrary.embeddings = new Map(data.embeddings);\n\n logger.info(`[FaceRecognition] Loaded ${this.faceLibrary.faces.size} face profiles`);\n } catch (error) {\n logger.warn(\"[FaceRecognition] Could not load face library:\", error);\n }\n }\n}\n",
13
- "import { logger } from \"@elizaos/core\";\nimport { Florence2Local } from \"./florence2-local\";\nimport type { BoundingBox, Florence2Result, ScreenTile } from \"./types\";\n\nexport class Florence2Model {\n private initialized = false;\n private localModel: Florence2Local;\n\n constructor() {\n this.localModel = new Florence2Local();\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n try {\n logger.info(\"[Florence2] Initializing local Florence-2 model with TensorFlow.js...\");\n\n await this.localModel.initialize();\n\n this.initialized = true;\n logger.info(\"[Florence2] Local model initialized successfully\");\n } catch (error) {\n logger.error(\"[Florence2] Failed to initialize local model:\", error);\n // Don't throw - we have good fallbacks\n this.initialized = true;\n logger.warn(\"[Florence2] Running with enhanced fallback mode\");\n }\n }\n\n async analyzeTile(tile: ScreenTile): Promise<Florence2Result> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n if (!tile.data) {\n throw new Error(\"Tile has no image data\");\n }\n\n try {\n // Use local model\n try {\n const result = await this.localModel.analyzeImage(tile.data);\n logger.debug(`[Florence2] Analyzed tile ${tile.id}: ${result.caption}`);\n return result;\n } catch (_modelError) {\n logger.warn(\"[Florence2] Local model analysis failed, falling back:\", _modelError);\n }\n\n // Fall back to mock analysis\n const result = await this.mockAnalyze(tile);\n logger.debug(`[Florence2] Mock analyzed tile ${tile.id}: ${result.caption}`);\n return result;\n } catch (error) {\n logger.error(\"[Florence2] Analysis failed:\", error);\n throw error;\n }\n }\n\n async analyzeImage(imageBuffer: Buffer): Promise<Florence2Result> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n try {\n // Use local model\n try {\n const result = await this.localModel.analyzeImage(imageBuffer);\n logger.debug(`[Florence2] Analyzed image: ${result.caption}`);\n return result;\n } catch (_modelError) {\n logger.warn(\"[Florence2] Local model analysis failed, falling back:\", _modelError);\n }\n\n // Fall back to mock analysis\n const result = await this.mockAnalyzeBuffer(imageBuffer);\n logger.debug(`[Florence2] Mock analyzed image: ${result.caption}`);\n return result;\n } catch (error) {\n logger.error(\"[Florence2] Image analysis failed:\", error);\n throw error;\n }\n }\n\n private async mockAnalyze(tile: ScreenTile): Promise<Florence2Result> {\n // Mock implementation that simulates Florence-2 output\n // In production, this would be replaced with actual API calls\n\n const isUpperRegion = tile.row < 2;\n const isLeftRegion = tile.col < 2;\n\n // Simulate different UI regions\n let caption = \"Desktop screen region\";\n const objects: Array<{ label: string; bbox: BoundingBox; confidence: number }> = [];\n const regions: Array<{ description: string; bbox: BoundingBox }> = [];\n const tags: string[] = [];\n\n if (isUpperRegion) {\n caption = \"Application window with menu bar\";\n objects.push({\n label: \"window\",\n bbox: { x: 0, y: 0, width: tile.width, height: 50 },\n confidence: 0.9,\n });\n objects.push({\n label: \"menu_bar\",\n bbox: { x: 0, y: 0, width: tile.width, height: 30 },\n confidence: 0.85,\n });\n tags.push(\"ui\", \"application\", \"desktop\");\n }\n\n if (isLeftRegion) {\n caption = \"Sidebar or navigation area\";\n objects.push({\n label: \"sidebar\",\n bbox: { x: 0, y: 0, width: 100, height: tile.height },\n confidence: 0.8,\n });\n tags.push(\"navigation\", \"sidebar\");\n }\n\n // Add some common UI elements\n const buttonCount = Math.floor(Math.random() * 3) + 1;\n for (let i = 0; i < buttonCount; i++) {\n objects.push({\n label: \"button\",\n bbox: {\n x: Math.random() * (tile.width - 100),\n y: Math.random() * (tile.height - 40),\n width: 100,\n height: 40,\n },\n confidence: 0.7 + Math.random() * 0.2,\n });\n }\n\n // Add text regions\n const textRegions = Math.floor(Math.random() * 2) + 1;\n for (let i = 0; i < textRegions; i++) {\n regions.push({\n description: \"Text content area\",\n bbox: {\n x: Math.random() * (tile.width - 200),\n y: Math.random() * (tile.height - 100),\n width: 200,\n height: 100,\n },\n });\n }\n\n tags.push(\"screen\", \"interface\", \"computer\");\n\n return {\n caption,\n objects,\n regions,\n tags,\n };\n }\n\n async detectUIElements(imageBuffer: Buffer): Promise<\n Array<{\n type: string;\n bbox: BoundingBox;\n confidence: number;\n text?: string;\n }>\n > {\n if (!this.initialized) {\n await this.initialize();\n }\n\n try {\n // Use local model to analyze image\n let result: Florence2Result;\n\n try {\n result = await this.localModel.analyzeImage(imageBuffer);\n } catch (_modelError) {\n logger.warn(\"[Florence2] Local model failed for UI detection, using fallback\");\n result = await this.mockAnalyzeBuffer(imageBuffer);\n }\n\n // Convert Florence-2 objects to UI elements\n return (result.objects || []).map((obj) => ({\n type: this.mapToUIElementType(obj.label),\n bbox: obj.bbox,\n confidence: obj.confidence,\n }));\n } catch (error) {\n logger.error(\"[Florence2] UI element detection failed:\", error);\n return [];\n }\n }\n\n private async mockAnalyzeBuffer(_imageBuffer: Buffer): Promise<Florence2Result> {\n // Enhanced mock for when API is not available\n // Provides more realistic descriptions based on common scenarios\n\n const scenarios = [\n {\n caption: \"Indoor scene with a person in front of a computer\",\n objects: [\n {\n label: \"person\",\n bbox: { x: 300, y: 200, width: 200, height: 300 },\n confidence: 0.9,\n },\n {\n label: \"computer\",\n bbox: { x: 400, y: 350, width: 150, height: 100 },\n confidence: 0.85,\n },\n {\n label: \"desk\",\n bbox: { x: 350, y: 400, width: 250, height: 100 },\n confidence: 0.8,\n },\n ],\n tags: [\"indoor\", \"office\", \"workspace\", \"person\", \"computer\"],\n },\n {\n caption: \"Room interior with furniture and lighting\",\n objects: [\n {\n label: \"chair\",\n bbox: { x: 200, y: 300, width: 100, height: 150 },\n confidence: 0.85,\n },\n {\n label: \"table\",\n bbox: { x: 350, y: 350, width: 150, height: 100 },\n confidence: 0.8,\n },\n {\n label: \"lamp\",\n bbox: { x: 500, y: 200, width: 50, height: 100 },\n confidence: 0.75,\n },\n ],\n tags: [\"indoor\", \"room\", \"furniture\", \"interior\"],\n },\n {\n caption: \"Person working at a desk with computer monitor\",\n objects: [\n {\n label: \"person\",\n bbox: { x: 250, y: 150, width: 250, height: 350 },\n confidence: 0.92,\n },\n {\n label: \"monitor\",\n bbox: { x: 450, y: 300, width: 120, height: 80 },\n confidence: 0.88,\n },\n {\n label: \"keyboard\",\n bbox: { x: 430, y: 380, width: 100, height: 30 },\n confidence: 0.82,\n },\n ],\n tags: [\"person\", \"working\", \"computer\", \"desk\", \"office\"],\n },\n ];\n\n // Randomly select a scenario for variety\n const scenario = scenarios[Math.floor(Math.random() * scenarios.length)];\n\n return {\n caption: scenario.caption,\n objects: scenario.objects,\n regions: [],\n tags: scenario.tags,\n };\n }\n\n private mapToUIElementType(label: string): string {\n const mapping: Record<string, string> = {\n button: \"button\",\n text_field: \"input\",\n text_area: \"textarea\",\n checkbox: \"checkbox\",\n radio_button: \"radio\",\n dropdown: \"select\",\n menu: \"menu\",\n menu_bar: \"menubar\",\n toolbar: \"toolbar\",\n window: \"window\",\n dialog: \"dialog\",\n icon: \"icon\",\n image: \"image\",\n video: \"video\",\n link: \"link\",\n heading: \"heading\",\n paragraph: \"text\",\n list: \"list\",\n table: \"table\",\n scrollbar: \"scrollbar\",\n tab: \"tab\",\n panel: \"panel\",\n };\n\n return mapping[label.toLowerCase()] || \"unknown\";\n }\n\n async generateSceneGraph(tiles: ScreenTile[]): Promise<{\n nodes: Array<{ id: string; type: string; label: string; position: BoundingBox }>;\n edges: Array<{ source: string; target: string; relation: string }>;\n }> {\n const nodes: Array<{ id: string; type: string; label: string; position: BoundingBox }> = [];\n const edges: Array<{ source: string; target: string; relation: string }> = [];\n\n // Analyze each tile\n for (const tile of tiles) {\n if (!tile.data) {\n continue;\n }\n\n const analysis = await this.analyzeTile(tile);\n\n // Add objects as nodes\n if (analysis.objects) {\n for (const obj of analysis.objects) {\n const nodeId = `${tile.id}-${obj.label}-${nodes.length}`;\n nodes.push({\n id: nodeId,\n type: obj.label,\n label: obj.label,\n position: {\n x: tile.x + obj.bbox.x,\n y: tile.y + obj.bbox.y,\n width: obj.bbox.width,\n height: obj.bbox.height,\n },\n });\n }\n }\n }\n\n // Infer spatial relationships\n for (let i = 0; i < nodes.length; i++) {\n for (let j = i + 1; j < nodes.length; j++) {\n const relation = this.inferSpatialRelation(nodes[i].position, nodes[j].position);\n if (relation) {\n edges.push({\n source: nodes[i].id,\n target: nodes[j].id,\n relation,\n });\n }\n }\n }\n\n return { nodes, edges };\n }\n\n private inferSpatialRelation(box1: BoundingBox, box2: BoundingBox): string | null {\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 // Check containment\n if (this.contains(box1, box2)) {\n return \"contains\";\n }\n if (this.contains(box2, box1)) {\n return \"contained_by\";\n }\n\n // Check overlap\n if (this.overlaps(box1, box2)) {\n return \"overlaps\";\n }\n\n // Check adjacency and direction\n const dx = center2.x - center1.x;\n const dy = center2.y - center1.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n if (distance < 100) {\n // Close proximity\n if (Math.abs(dx) > Math.abs(dy)) {\n return dx > 0 ? \"right_of\" : \"left_of\";\n } else {\n return dy > 0 ? \"below\" : \"above\";\n }\n }\n\n return null;\n }\n\n private contains(box1: BoundingBox, box2: BoundingBox): boolean {\n return (\n box1.x <= box2.x &&\n box1.y <= box2.y &&\n box1.x + box1.width >= box2.x + box2.width &&\n box1.y + box1.height >= box2.y + box2.height\n );\n }\n\n private overlaps(box1: BoundingBox, box2: BoundingBox): boolean {\n return !(\n box1.x + box1.width < box2.x ||\n box2.x + box2.width < box1.x ||\n box1.y + box1.height < box2.y ||\n box2.y + box2.height < box1.y\n );\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n async dispose(): Promise<void> {\n // Clean up resources if needed\n this.initialized = false;\n logger.info(\"[Florence2] Model disposed\");\n }\n}\n",
14
- "import { logger } from \"@elizaos/core\";\nimport sharp from \"sharp\";\nimport type { Florence2Result } from \"./types\";\n\n// Lazy-loaded TensorFlow.js — the native addon may not be available.\nlet tf: typeof import(\"@tensorflow/tfjs-node\") | null = null;\n\nasync function ensureTf(): Promise<boolean> {\n if (tf) return true;\n try {\n tf = await import(\"@tensorflow/tfjs-node\");\n return true;\n } catch {\n logger.warn(\n \"[Florence2Local] TensorFlow.js native addon not available — using heuristic analysis.\",\n );\n return false;\n }\n}\n\ninterface VisionModelConfig {\n modelUrl?: string;\n cacheDir?: string;\n}\n\ninterface ResolvedVisionModelConfig {\n modelUrl: string;\n cacheDir: string;\n}\n\n/**\n * Local vision model for basic image analysis using MobileNet.\n * Provides caption generation and basic scene understanding capabilities.\n */\nexport class Florence2Local {\n private model: { predict: (input: ReturnType<NonNullable<typeof tf>[\"tensor\"]>) => ReturnType<NonNullable<typeof tf>[\"tensor\"]>; dispose: () => void } | null = null;\n private initialized = false;\n private config: ResolvedVisionModelConfig;\n\n constructor(config?: VisionModelConfig) {\n this.config = {\n modelUrl:\n config?.modelUrl ||\n \"https://tfhub.dev/google/tfjs-model/imagenet/mobilenet_v3_small_100_224/feature_vector/5/default/1\",\n cacheDir: config?.cacheDir || \"./models/cache\",\n };\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n const tfAvailable = await ensureTf();\n if (!tfAvailable || !tf) {\n // Continue without model — will use heuristic-based analysis\n this.initialized = true;\n return;\n }\n\n try {\n logger.info(\"[VisionModel] Initializing MobileNet model for image analysis...\");\n\n this.model = (await tf.loadGraphModel(this.config.modelUrl)) as typeof this.model;\n\n this.initialized = true;\n logger.info(\"[VisionModel] Model initialized successfully\");\n } catch (error) {\n logger.error(\"[VisionModel] Failed to initialize model:\", error);\n // Continue without model - will use heuristic-based analysis\n this.initialized = true;\n }\n }\n\n async analyzeImage(imageBuffer: Buffer): Promise<Florence2Result> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n // If TF isn't available or model didn't load, skip directly to fallback\n if (!tf || !this.model) {\n return await this.enhancedFallback(imageBuffer);\n }\n\n try {\n // Preprocess image\n const preprocessed = await this.preprocessImage(imageBuffer);\n\n // Run inference\n const predictions = await this.runInference(preprocessed);\n (preprocessed as { dispose?: () => void }).dispose?.();\n\n return this.parseModelOutput(predictions as Parameters<typeof this.parseModelOutput>[0]);\n } catch (error) {\n logger.error(\"[VisionModel] Analysis failed:\", error);\n return await this.enhancedFallback(imageBuffer);\n }\n }\n\n private async preprocessImage(imageBuffer: Buffer) {\n if (!tf) throw new Error(\"TensorFlow.js not available\");\n\n // Resize and normalize image for model input\n const resized = await sharp(imageBuffer)\n .resize(224, 224) // MobileNet uses 224x224\n .raw()\n .toBuffer();\n\n // Convert to tensor and normalize\n const tensor = tf.node.decodeImage(resized, 3);\n const normalized = tf.div(tensor, 255.0);\n\n return normalized;\n }\n\n private async runInference(input: { expandDims: (axis: number) => { dispose: () => void } }) {\n if (!this.model) {\n throw new Error(\"Model not loaded\");\n }\n\n // Add batch dimension\n const batched = input.expandDims(0);\n\n // Run model\n const output = this.model.predict(batched as Parameters<typeof this.model.predict>[0]);\n\n batched.dispose();\n\n return output;\n }\n\n private async parseModelOutput(predictions: { array: () => Promise<number[][]>; dispose: () => void }): Promise<Florence2Result> {\n const values = await predictions.array();\n predictions.dispose();\n\n const caption = this.generateCaptionFromFeatures(values);\n\n return {\n caption,\n objects: [],\n regions: [],\n tags: this.extractTagsFromCaption(caption),\n };\n }\n\n private generateCaptionFromFeatures(features: number[][]): string {\n const scenes = [\n \"Indoor scene with various objects visible\",\n \"Person in a room with furniture\",\n \"Computer workspace with monitor and desk\",\n \"Living space with natural lighting\",\n \"Office environment with equipment\",\n ];\n\n const index = Math.abs(features[0][0]) * scenes.length;\n return scenes[Math.floor(index) % scenes.length];\n }\n\n private extractTagsFromCaption(caption: string): string[] {\n const words = caption.toLowerCase().split(/\\s+/);\n const validTags = [\n \"indoor\",\n \"outdoor\",\n \"person\",\n \"computer\",\n \"desk\",\n \"office\",\n \"room\",\n \"furniture\",\n \"monitor\",\n \"workspace\",\n ];\n return words.filter((word) => validTags.includes(word));\n }\n\n private async enhancedFallback(imageBuffer: Buffer): Promise<Florence2Result> {\n // Analyze image properties for better fallback\n const metadata = await sharp(imageBuffer).metadata();\n const stats = await sharp(imageBuffer).stats();\n\n // Determine scene type based on image characteristics\n const brightness =\n (stats.channels[0].mean + stats.channels[1].mean + stats.channels[2].mean) / 3;\n const isIndoor = brightness < 180; // Simplified heuristic\n\n // Generate contextual caption\n let caption = isIndoor ? \"Indoor scene\" : \"Outdoor scene\";\n\n // Add more context based on image properties\n if (metadata.width && metadata.height) {\n const aspectRatio = metadata.width / metadata.height;\n if (aspectRatio > 1.5) {\n caption += \" with wide field of view\";\n } else if (aspectRatio < 0.7) {\n caption += \" in portrait orientation\";\n }\n }\n\n // Detect dominant colors for additional context\n const dominantColor = stats.dominant;\n if (dominantColor.r > 200 && dominantColor.g > 200 && dominantColor.b > 200) {\n caption += \", well-lit environment\";\n } else if (dominantColor.r < 100 && dominantColor.g < 100 && dominantColor.b < 100) {\n caption += \", dimly lit conditions\";\n }\n\n return {\n caption,\n objects: [],\n regions: [],\n tags: this.extractTagsFromCaption(caption),\n };\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n async dispose(): Promise<void> {\n if (this.model) {\n this.model.dispose();\n this.model = null;\n }\n this.initialized = false;\n logger.info(\"[VisionModel] Model disposed\");\n }\n}\n",
15
- "import { logger } from \"@elizaos/core\";\nimport { RealOCRService } from \"./ocr-service-real\";\nimport type { BoundingBox, OCRResult, ScreenTile } from \"./types\";\n\nexport class OCRService {\n private realOCR: RealOCRService | null = null;\n private initialized = false;\n private useFallback = false;\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n try {\n logger.info(\"[OCR] Initializing OCR service...\");\n\n // Try to use real OCR first\n this.realOCR = new RealOCRService();\n await this.realOCR.initialize();\n\n this.initialized = true;\n this.useFallback = false;\n logger.info(\"[OCR] Real OCR service initialized successfully\");\n } catch (error) {\n logger.error(\"[OCR] Failed to initialize real OCR:\", error);\n\n // Fallback to basic OCR simulation\n logger.warn(\"[OCR] Using fallback OCR implementation\");\n this.useFallback = true;\n this.initialized = true;\n }\n }\n\n async extractText(imageBuffer: Buffer): Promise<OCRResult> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n // Use real OCR if available\n if (this.realOCR && !this.useFallback) {\n try {\n return await this.realOCR.extractText(imageBuffer);\n } catch (error) {\n logger.error(\"[OCR] Real OCR failed, falling back:\", error);\n this.useFallback = true;\n }\n }\n\n // Fallback implementation\n return this.fallbackOCR(imageBuffer);\n }\n\n async extractFromTile(tile: ScreenTile): Promise<OCRResult> {\n if (!tile.data) {\n return {\n text: \"\",\n blocks: [],\n fullText: \"\",\n };\n }\n\n return this.extractText(tile.data);\n }\n\n async extractFromImage(imageBuffer: Buffer): Promise<OCRResult> {\n return this.extractText(imageBuffer);\n }\n\n private async fallbackOCR(_imageBuffer: Buffer): Promise<OCRResult> {\n // Fallback implementation for when Tesseract is not available\n logger.debug(\"[OCR] Using fallback OCR implementation\");\n\n const blocks: Array<{\n text: string;\n bbox: BoundingBox;\n confidence: number;\n words?: Array<{\n text: string;\n bbox: BoundingBox;\n confidence: number;\n }>;\n }> = [];\n\n // Simulate finding common UI text\n const mockTexts = [\n { text: \"File Edit View Window Help\", x: 10, y: 5, width: 300, height: 20 },\n { text: \"Welcome to the application\", x: 100, y: 100, width: 400, height: 40 },\n { text: \"Click here to continue\", x: 200, y: 300, width: 200, height: 30 },\n ];\n\n for (const mock of mockTexts) {\n blocks.push({\n text: mock.text,\n bbox: { x: mock.x, y: mock.y, width: mock.width, height: mock.height },\n confidence: 0.85 + Math.random() * 0.1,\n });\n }\n\n const fullText = blocks.map((b) => b.text).join(\"\\n\");\n\n return {\n text: fullText,\n blocks,\n fullText,\n };\n }\n\n async extractStructuredData(imageBuffer: Buffer): Promise<{\n tables?: Array<{ rows: string[][]; bbox: BoundingBox }>;\n forms?: Array<{ label: string; value: string; bbox: BoundingBox }>;\n lists?: Array<{ items: string[]; bbox: BoundingBox }>;\n }> {\n if (this.realOCR && !this.useFallback) {\n try {\n return await this.realOCR.extractStructuredData(imageBuffer);\n } catch (error) {\n logger.error(\"[OCR] Structured data extraction failed:\", error);\n }\n }\n\n // Fallback: return empty structured data\n return {\n tables: [],\n forms: [],\n lists: [],\n };\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n async dispose(): Promise<void> {\n if (this.realOCR) {\n await this.realOCR.dispose();\n this.realOCR = null;\n }\n this.initialized = false;\n this.useFallback = false;\n logger.info(\"[OCR] Service disposed\");\n }\n}\n",
16
- "import { logger } from \"@elizaos/core\";\nimport sharp from \"sharp\";\nimport Tesseract from \"tesseract.js\";\nimport type { BoundingBox, OCRResult, ScreenTile } from \"./types\";\n\nexport class RealOCRService {\n private worker: Tesseract.Worker | null = null;\n private initialized = false;\n private initPromise: Promise<void> | null = null;\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n // Prevent multiple initializations\n if (this.initPromise) {\n return this.initPromise;\n }\n\n this.initPromise = this._initialize();\n return this.initPromise;\n }\n\n private async _initialize(): Promise<void> {\n try {\n logger.info(\"[RealOCR] Initializing Tesseract.js...\");\n\n // Create worker\n this.worker = await Tesseract.createWorker(\"eng\", 1, {\n logger: (m) => {\n if (m.status === \"recognizing text\") {\n logger.debug(`[RealOCR] Progress: ${(m.progress * 100).toFixed(1)}%`);\n }\n },\n });\n\n this.initialized = true;\n logger.info(\"[RealOCR] Tesseract.js initialized successfully\");\n } catch (error) {\n logger.error(\"[RealOCR] Failed to initialize:\", error);\n throw error;\n }\n }\n\n async extractText(imageBuffer: Buffer): Promise<OCRResult> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n if (!this.worker) {\n throw new Error(\"OCR worker not initialized\");\n }\n\n try {\n // Preprocess image for better OCR\n const processedBuffer = await this.preprocessImage(imageBuffer);\n\n // Perform OCR\n const result = await this.worker.recognize(processedBuffer);\n\n // Convert Tesseract result to our format\n return this.convertTesseractResult(result);\n } catch (error) {\n logger.error(\"[RealOCR] Text extraction failed:\", error);\n throw error;\n }\n }\n\n async extractFromTile(tile: ScreenTile): Promise<OCRResult> {\n if (!tile.data) {\n return {\n text: \"\",\n blocks: [],\n fullText: \"\",\n };\n }\n\n return this.extractText(tile.data);\n }\n\n private async preprocessImage(imageBuffer: Buffer): Promise<Buffer> {\n try {\n // Enhance image for better OCR results\n const processed = await sharp(imageBuffer)\n .grayscale() // Convert to grayscale\n .normalize() // Normalize contrast\n .sharpen() // Sharpen text\n .toBuffer();\n\n return processed;\n } catch (error) {\n logger.warn(\"[RealOCR] Image preprocessing failed, using original:\", error);\n return imageBuffer;\n }\n }\n\n private convertTesseractResult(result: Tesseract.RecognizeResult): OCRResult {\n const blocks: OCRResult[\"blocks\"] = [];\n\n // Process lines as blocks - Tesseract result.data has lines property\n interface TesseractLine {\n text: string;\n confidence: number;\n bbox: { x0: number; y0: number; x1: number; y1: number };\n words: Array<{\n text: string;\n confidence: number;\n bbox: { x0: number; y0: number; x1: number; y1: number };\n }>;\n }\n const data = result.data as { lines?: TesseractLine[]; text: string };\n const lines = data.lines || [];\n for (const line of lines) {\n if (line.confidence > 30) {\n // Filter low confidence\n blocks.push({\n text: line.text.trim(),\n bbox: {\n x: line.bbox.x0,\n y: line.bbox.y0,\n width: line.bbox.x1 - line.bbox.x0,\n height: line.bbox.y1 - line.bbox.y0,\n },\n confidence: line.confidence / 100,\n words: line.words.map((word) => ({\n text: word.text,\n bbox: {\n x: word.bbox.x0,\n y: word.bbox.y0,\n width: word.bbox.x1 - word.bbox.x0,\n height: word.bbox.y1 - word.bbox.y0,\n },\n confidence: word.confidence / 100,\n })),\n });\n }\n }\n\n const fullText = result.data.text.trim();\n\n return {\n text: fullText,\n blocks,\n fullText,\n };\n }\n\n async extractStructuredData(imageBuffer: Buffer): Promise<{\n tables?: Array<{ rows: string[][]; bbox: BoundingBox }>;\n forms?: Array<{ label: string; value: string; bbox: BoundingBox }>;\n lists?: Array<{ items: string[]; bbox: BoundingBox }>;\n }> {\n const ocrResult = await this.extractText(imageBuffer);\n\n return {\n tables: this.detectTables(ocrResult),\n forms: this.detectForms(ocrResult),\n lists: this.detectLists(ocrResult),\n };\n }\n\n private detectTables(ocrResult: OCRResult): Array<{ rows: string[][]; bbox: BoundingBox }> {\n const tables: Array<{ rows: string[][]; bbox: BoundingBox }> = [];\n\n // Group blocks by vertical alignment to detect table rows\n const rows: Map<number, typeof ocrResult.blocks> = new Map();\n\n for (const block of ocrResult.blocks) {\n // Round Y position to group nearby blocks\n const rowY = Math.round(block.bbox.y / 20) * 20;\n\n if (!rows.has(rowY)) {\n rows.set(rowY, []);\n }\n rows.get(rowY)?.push(block);\n }\n\n // Find potential tables (multiple aligned rows)\n const sortedRows = Array.from(rows.entries()).sort((a, b) => a[0] - b[0]);\n\n let tableRows: string[][] = [];\n let tableBounds: BoundingBox | null = null;\n\n for (const [y, rowBlocks] of sortedRows) {\n if (rowBlocks.length > 1) {\n // Sort blocks by X position\n rowBlocks.sort((a, b) => a.bbox.x - b.bbox.x);\n\n const rowTexts = rowBlocks.map((b) => b.text);\n tableRows.push(rowTexts);\n\n // Update table bounds\n if (!tableBounds) {\n tableBounds = { ...rowBlocks[0].bbox };\n } else {\n tableBounds.x = Math.min(tableBounds.x, rowBlocks[0].bbox.x);\n tableBounds.width =\n Math.max(...rowBlocks.map((b) => b.bbox.x + b.bbox.width)) - tableBounds.x;\n tableBounds.height = y + rowBlocks[0].bbox.height - tableBounds.y;\n }\n } else if (tableRows.length > 1 && tableBounds) {\n // End of table\n tables.push({\n rows: [...tableRows],\n bbox: { ...tableBounds },\n });\n tableRows = [];\n tableBounds = null;\n }\n }\n\n // Add final table if exists\n if (tableRows.length > 1 && tableBounds) {\n tables.push({\n rows: tableRows,\n bbox: tableBounds,\n });\n }\n\n return tables;\n }\n\n private detectForms(\n ocrResult: OCRResult\n ): Array<{ label: string; value: string; bbox: BoundingBox }> {\n const forms: Array<{ label: string; value: string; bbox: BoundingBox }> = [];\n\n // Look for label-value patterns\n const blocks = ocrResult.blocks;\n\n for (let i = 0; i < blocks.length; i++) {\n const current = blocks[i];\n\n // Check if this looks like a label\n if (current.text.match(/[::]\\s*$/)) {\n const label = current.text.replace(/[::]\\s*$/, \"\").trim();\n\n // Look for value in nearby blocks\n for (let j = i + 1; j < blocks.length && j < i + 3; j++) {\n const next = blocks[j];\n\n // Check if horizontally aligned or just below\n const isAligned = Math.abs(current.bbox.y - next.bbox.y) < 10;\n const isBelow =\n next.bbox.y > current.bbox.y && next.bbox.y < current.bbox.y + current.bbox.height + 30;\n\n if (isAligned || isBelow) {\n forms.push({\n label,\n value: next.text.trim(),\n bbox: {\n x: Math.min(current.bbox.x, next.bbox.x),\n y: current.bbox.y,\n width:\n Math.max(current.bbox.x + current.bbox.width, next.bbox.x + next.bbox.width) -\n Math.min(current.bbox.x, next.bbox.x),\n height: next.bbox.y + next.bbox.height - current.bbox.y,\n },\n });\n break;\n }\n }\n }\n }\n\n return forms;\n }\n\n private detectLists(ocrResult: OCRResult): Array<{ items: string[]; bbox: BoundingBox }> {\n const lists: Array<{ items: string[]; bbox: BoundingBox }> = [];\n\n let currentList: string[] = [];\n let listBounds: BoundingBox | null = null;\n\n for (const block of ocrResult.blocks) {\n // Check for list markers\n const listMatch = block.text.match(/^[\\u2022\\u2023\\u25E6\\u2043\\u2219•·‣⁃◦▪▫◆◇○●\\-*]\\s+(.+)$/);\n const numberedMatch = block.text.match(/^(\\d+\\.|\\d+\\)|\\(\\d+\\)|[a-zA-Z]\\.)\\s+(.+)$/);\n\n if (listMatch || numberedMatch) {\n const itemText = listMatch ? listMatch[1] : numberedMatch?.[2];\n currentList.push(itemText.trim());\n\n if (!listBounds) {\n listBounds = { ...block.bbox };\n } else {\n listBounds.width = Math.max(\n listBounds.width,\n block.bbox.x + block.bbox.width - listBounds.x\n );\n listBounds.height = block.bbox.y + block.bbox.height - listBounds.y;\n }\n } else if (currentList.length > 0 && listBounds) {\n // End of list\n lists.push({\n items: [...currentList],\n bbox: { ...listBounds },\n });\n currentList = [];\n listBounds = null;\n }\n }\n\n // Add final list if exists\n if (currentList.length > 0 && listBounds) {\n lists.push({\n items: currentList,\n bbox: listBounds,\n });\n }\n\n return lists;\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n async dispose(): Promise<void> {\n if (this.worker) {\n await this.worker.terminate();\n this.worker = null;\n }\n this.initialized = false;\n this.initPromise = null;\n logger.info(\"[RealOCR] Disposed\");\n }\n}\n",
17
- "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 { logger } from \"@elizaos/core\";\nimport sharp from \"sharp\";\nimport type { ScreenCapture, ScreenTile, VisionConfig } from \"./types\";\n\nconst execAsync = promisify(exec);\n\nexport class ScreenCaptureService {\n private config: VisionConfig;\n private activeTileIndex = 0;\n private lastCapture: ScreenCapture | null = null;\n\n constructor(config: VisionConfig) {\n this.config = config;\n }\n\n async getScreenInfo(): Promise<{ width: number; height: number } | null> {\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\n if (data.SPDisplaysDataType?.[0]) {\n const display = data.SPDisplaysDataType[0];\n const resolution = display._items?.[0]?.native_resolution;\n if (resolution) {\n const match = resolution.match(/(\\d+) x (\\d+)/);\n if (match) {\n return {\n width: parseInt(match[1], 10),\n height: parseInt(match[2], 10),\n };\n }\n }\n }\n } else if (platform === \"linux\") {\n // Linux: Use xrandr\n const { stdout } = await execAsync('xrandr | grep \" connected primary\"');\n const match = stdout.match(/(\\d+)x(\\d+)/);\n if (match) {\n return {\n width: parseInt(match[1], 10),\n height: parseInt(match[2], 10),\n };\n }\n } else if (platform === \"win32\") {\n // Windows: Use wmic\n const { stdout } = await execAsync(\n \"wmic path Win32_VideoController get CurrentHorizontalResolution,CurrentVerticalResolution /value\"\n );\n const width = stdout.match(/CurrentHorizontalResolution=(\\d+)/)?.[1];\n const height = stdout.match(/CurrentVerticalResolution=(\\d+)/)?.[1];\n if (width && height) {\n return {\n width: parseInt(width, 10),\n height: parseInt(height, 10),\n };\n }\n }\n } catch (error) {\n logger.error(\"[ScreenCapture] Failed to get screen info:\", error);\n }\n\n // Default fallback\n return { width: 1920, height: 1080 };\n }\n\n async captureScreen(): Promise<ScreenCapture> {\n const tempFile = path.join(process.cwd(), `temp_screen_${Date.now()}.png`);\n\n try {\n // Capture the screen\n await this.captureScreenToFile(tempFile);\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 || 1920;\n const height = metadata.height || 1080;\n\n // Create tiles\n const tileSize = this.config.tileSize || 256;\n const tiles: ScreenTile[] = [];\n\n for (let row = 0; row < Math.ceil(height / tileSize); row++) {\n for (let col = 0; col < Math.ceil(width / tileSize); col++) {\n const x = col * tileSize;\n const y = row * tileSize;\n const tileWidth = Math.min(tileSize, width - x);\n const tileHeight = Math.min(tileSize, height - y);\n\n tiles.push({\n id: `tile-${row}-${col}`,\n row,\n col,\n x,\n y,\n width: tileWidth,\n height: tileHeight,\n });\n }\n }\n\n // Process active tile based on order\n if (this.config.tileProcessingOrder === \"priority\") {\n // Focus on center tiles first\n const centerRow = Math.floor(tiles.length / 2 / Math.ceil(width / tileSize));\n const centerCol = Math.floor((tiles.length / 2) % Math.ceil(width / tileSize));\n this.activeTileIndex = centerRow * Math.ceil(width / tileSize) + centerCol;\n } else if (this.config.tileProcessingOrder === \"random\") {\n this.activeTileIndex = Math.floor(Math.random() * tiles.length);\n } else {\n // Sequential\n this.activeTileIndex = (this.activeTileIndex + 1) % tiles.length;\n }\n\n // Extract active tile data\n const activeTile = tiles[this.activeTileIndex];\n if (activeTile) {\n try {\n const tileBuffer = await image\n .extract({\n left: activeTile.x,\n top: activeTile.y,\n width: activeTile.width,\n height: activeTile.height,\n })\n .png()\n .toBuffer();\n\n activeTile.data = tileBuffer;\n } catch (error) {\n logger.error(\"[ScreenCapture] Failed to extract tile:\", error);\n }\n }\n\n // Clean up temp file\n await fs.unlink(tempFile).catch(() => {});\n\n // Create screen capture object\n const capture: ScreenCapture = {\n timestamp: Date.now(),\n width,\n height,\n data: imageBuffer,\n tiles,\n };\n\n this.lastCapture = capture;\n return capture;\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): Promise<void> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // macOS: Use screencapture\n await execAsync(`screencapture -x \"${outputPath}\"`);\n } else if (platform === \"linux\") {\n // Linux: Use scrot or gnome-screenshot\n try {\n await execAsync(`scrot \"${outputPath}\"`);\n } catch (_error) {\n // Fallback to gnome-screenshot\n await execAsync(`gnome-screenshot -f \"${outputPath}\"`);\n }\n } else if (platform === \"win32\") {\n // Windows: Use PowerShell\n const script = `\n Add-Type -AssemblyName System.Windows.Forms;\n Add-Type -AssemblyName System.Drawing;\n $screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds;\n $bitmap = New-Object System.Drawing.Bitmap $screen.Width, $screen.Height;\n $graphics = [System.Drawing.Graphics]::FromImage($bitmap);\n $graphics.CopyFromScreen($screen.Location, [System.Drawing.Point]::Empty, $screen.Size);\n $bitmap.Save('${outputPath.replace(/\\\\/g, \"\\\\\\\\\")}');\n $graphics.Dispose();\n $bitmap.Dispose();\n `;\n await execAsync(`powershell -Command \"${script.replace(/\\n/g, \" \")}\"`);\n } else {\n throw new Error(`Unsupported platform: ${platform}`);\n }\n } catch (error) {\n logger.error(\"[ScreenCapture] Screen capture failed:\", error);\n\n // Provide helpful error messages\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (platform === \"linux\" && errorMessage.includes(\"command not found\")) {\n throw new Error(\"Screen capture tool not found. Install with: sudo apt-get install scrot\");\n }\n throw error;\n }\n }\n\n getActiveTile(): ScreenTile | null {\n if (!this.lastCapture || !this.lastCapture.tiles[this.activeTileIndex]) {\n return null;\n }\n return this.lastCapture.tiles[this.activeTileIndex];\n }\n\n getAllTiles(): ScreenTile[] {\n return this.lastCapture?.tiles || [];\n }\n\n getProcessedTiles(): ScreenTile[] {\n return this.lastCapture?.tiles.filter((t) => t.analysis) || [];\n }\n}\n",
18
- "// Vision models for object detection and pose estimation\n\nimport { logger } from \"@elizaos/core\";\nimport type { DetectedObject, PersonInfo } from \"./types\";\n\n// Lazy-loaded TensorFlow.js modules — the native addon may not be available\n// (e.g. when installed via bun or on platforms without prebuilt binaries).\n// We load them on first use so the rest of the plugin still works.\nlet tf: typeof import(\"@tensorflow/tfjs-node\") | null = null;\nlet cocoSsd: typeof import(\"@tensorflow-models/coco-ssd\") | null = null;\nlet poseDetection: typeof import(\"@tensorflow-models/pose-detection\") | null = null;\n\nasync function loadTfModules(): Promise<boolean> {\n if (tf) return true;\n try {\n tf = await import(\"@tensorflow/tfjs-node\");\n cocoSsd = await import(\"@tensorflow-models/coco-ssd\");\n poseDetection = await import(\"@tensorflow-models/pose-detection\");\n return true;\n } catch (err) {\n logger.warn(\n \"[VisionModels] TensorFlow.js native addon not available — \" +\n \"falling back to description-based detection. \" +\n \"Run `npm rebuild @tensorflow/tfjs-node --build-addon-from-source` to enable hardware-accelerated vision.\",\n );\n return false;\n }\n}\n\n// Define types that are missing from types.ts\nexport interface VisionModelConfig {\n enableObjectDetection?: boolean;\n enablePoseDetection?: boolean;\n florence2?: {\n baseUrl: string;\n apiKey?: string;\n };\n vlm?: {\n model: string;\n temperature: number;\n maxTokens: number;\n };\n}\n\nexport type Pose = \"sitting\" | \"standing\" | \"lying\" | \"walking\" | \"unknown\";\n\nexport interface PoseLandmark {\n name: string;\n x: number;\n y: number;\n score: number;\n}\n\nexport class VisionModels {\n private objectDetectionModel: Awaited<ReturnType<NonNullable<typeof cocoSsd>[\"load\"]>> | null = null;\n private poseDetector: Awaited<ReturnType<NonNullable<typeof poseDetection>[\"createDetector\"]>> | null = null;\n private initialized = false;\n private tfAvailable = false;\n\n async initialize(config: VisionModelConfig): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n logger.info(\"[VisionModels] Initializing vision models...\");\n\n this.tfAvailable = await loadTfModules();\n\n if (!this.tfAvailable || !tf || !cocoSsd || !poseDetection) {\n // Mark as initialized so we use the fallback paths instead of retrying.\n this.initialized = true;\n logger.info(\"[VisionModels] Initialized without TensorFlow (fallback mode)\");\n return;\n }\n\n try {\n // Initialize TensorFlow.js backend\n await tf.ready();\n logger.info(\"[VisionModels] TensorFlow.js backend ready\");\n\n // Load object detection model\n if (config.enableObjectDetection) {\n try {\n logger.info(\"[VisionModels] Loading COCO-SSD model...\");\n this.objectDetectionModel = await cocoSsd.load({\n base: \"mobilenet_v2\",\n });\n logger.info(\"[VisionModels] COCO-SSD model loaded\");\n } catch (error) {\n logger.error(\"[VisionModels] Failed to load COCO-SSD model:\", error);\n }\n }\n\n // Load pose detection model\n if (config.enablePoseDetection) {\n try {\n logger.info(\"[VisionModels] Loading PoseNet model...\");\n const detectorConfig = {\n architecture: \"MobileNetV1\" as const,\n outputStride: 16 as const,\n inputResolution: { width: 640, height: 480 },\n multiplier: 0.75 as const,\n };\n\n this.poseDetector = await poseDetection.createDetector(\n poseDetection.SupportedModels.PoseNet,\n detectorConfig\n );\n logger.info(\"[VisionModels] PoseNet model loaded\");\n } catch (error) {\n logger.error(\"[VisionModels] Failed to load PoseNet model:\", error);\n }\n }\n\n this.initialized = true;\n logger.info(\"[VisionModels] Vision models initialized\");\n } catch (error) {\n logger.error(\"[VisionModels] Initialization failed:\", error);\n throw error;\n }\n }\n\n hasObjectDetection(): boolean {\n return this.objectDetectionModel !== null;\n }\n\n hasPoseDetection(): boolean {\n return this.poseDetector !== null;\n }\n\n async detectObjects(\n imageData: Buffer,\n _width: number,\n _height: number,\n description?: string\n ): Promise<DetectedObject[]> {\n if (!this.objectDetectionModel || !tf) {\n logger.warn(\"[VisionModels] Object detection model not loaded\");\n return this.enhancedObjectDetection(description);\n }\n\n try {\n // Convert image data to tensor\n const imageTensor = tf.node.decodeImage(imageData, 3);\n\n // Ensure the tensor has the right shape [1, height, width, 3]\n const batched = imageTensor.expandDims(0);\n\n // Run detection - cocoSsd.detect expects specific input types\n // We squeeze the batch dimension back for detection\n const squeezed = batched.squeeze([0]) as ReturnType<typeof imageTensor.expandDims> extends infer T ? T : never;\n const predictions = await this.objectDetectionModel.detect(squeezed as Parameters<typeof this.objectDetectionModel.detect>[0]);\n squeezed.dispose();\n\n // Clean up tensors\n imageTensor.dispose();\n batched.dispose();\n\n // Convert predictions to our format\n const objects: DetectedObject[] = predictions.map((pred, idx) => ({\n id: `obj-${Date.now()}-${idx}`,\n type: pred.class,\n confidence: pred.score,\n boundingBox: {\n x: pred.bbox[0],\n y: pred.bbox[1],\n width: pred.bbox[2],\n height: pred.bbox[3],\n },\n }));\n\n logger.debug(`[VisionModels] Detected ${objects.length} objects`);\n return objects;\n } catch (error) {\n logger.error(\"[VisionModels] Object detection failed:\", error);\n return this.enhancedObjectDetection(description);\n }\n }\n\n private enhancedObjectDetection(description?: string): DetectedObject[] {\n // Enhanced object detection based on scene description\n if (!description) {\n return [];\n }\n\n const objects: DetectedObject[] = [];\n\n // Extract objects from description using patterns\n const objectPatterns = [\n { pattern: /(\\d+)?\\s*(person|people|man|men|woman|women|child|children)/gi, type: \"person\" },\n { pattern: /(\\d+)?\\s*(laptop|computer|monitor|screen|display)/gi, type: \"laptop\" },\n { pattern: /(\\d+)?\\s*(phone|smartphone|mobile)/gi, type: \"cell phone\" },\n { pattern: /(\\d+)?\\s*(book|notebook|journal)/gi, type: \"book\" },\n { pattern: /(\\d+)?\\s*(cup|mug|glass|bottle)/gi, type: \"cup\" },\n { pattern: /(\\d+)?\\s*(chair|seat|sofa|couch)/gi, type: \"chair\" },\n { pattern: /(\\d+)?\\s*(table|desk)/gi, type: \"dining table\" },\n { pattern: /(\\d+)?\\s*(car|vehicle|truck|bus)/gi, type: \"car\" },\n { pattern: /(\\d+)?\\s*(dog|cat|pet|animal)/gi, type: \"animal\" },\n { pattern: /(\\d+)?\\s*(plant|tree|flower)/gi, type: \"potted plant\" },\n ];\n\n for (const { pattern, type } of objectPatterns) {\n const matches = Array.from(description.matchAll(pattern));\n for (const match of matches) {\n const count = match[1] ? parseInt(match[1], 10) : 1;\n for (let i = 0; i < count; i++) {\n objects.push({\n id: `obj-${type}-${Date.now()}-${i}`,\n type,\n confidence: 0.85, // High confidence since it's from VLM\n boundingBox: this.generatePlausibleBoundingBox(type, i, count),\n });\n }\n }\n }\n\n return objects;\n }\n\n private generatePlausibleBoundingBox(\n type: string,\n index: number,\n total: number\n ): {\n x: number;\n y: number;\n width: number;\n height: number;\n } {\n // Generate plausible bounding boxes based on object type and position\n const basePositions: Record<string, { width: number; height: number; y: number }> = {\n person: { width: 150, height: 300, y: 100 },\n laptop: { width: 200, height: 150, y: 250 },\n \"cell phone\": { width: 50, height: 100, y: 300 },\n book: { width: 100, height: 150, y: 280 },\n cup: { width: 60, height: 80, y: 300 },\n chair: { width: 180, height: 200, y: 200 },\n \"dining table\": { width: 400, height: 200, y: 250 },\n car: { width: 300, height: 200, y: 150 },\n animal: { width: 120, height: 100, y: 300 },\n \"potted plant\": { width: 100, height: 150, y: 200 },\n };\n\n const base = basePositions[type] || { width: 100, height: 100, y: 200 };\n const spacing = 640 / (total + 1); // Distribute across frame width\n\n return {\n x: spacing * (index + 1) - base.width / 2,\n y: base.y + (Math.random() - 0.5) * 50,\n width: base.width + (Math.random() - 0.5) * 40,\n height: base.height + (Math.random() - 0.5) * 40,\n };\n }\n\n async detectPoses(\n imageData: Buffer,\n width: number,\n height: number,\n description?: string\n ): Promise<PersonInfo[]> {\n if (!this.poseDetector || !tf) {\n logger.warn(\"[VisionModels] Pose detection model not loaded\");\n return this.enhancedPoseDetection(description);\n }\n\n try {\n // Convert image data to tensor\n const imageTensor = tf.node.decodeImage(imageData, 3);\n\n // Run pose detection - estimatePoses expects ImageData-like object\n const poses = await this.poseDetector.estimatePoses({\n data: new Uint8ClampedArray(imageTensor.dataSync()),\n width,\n height,\n } as ImageData);\n\n // Clean up tensor\n imageTensor.dispose();\n\n // Convert poses to PersonInfo\n return this.convertPosesToPersonInfo(poses);\n } catch (error) {\n logger.error(\"[VisionModels] Pose detection failed:\", error);\n return this.enhancedPoseDetection(description);\n }\n }\n\n private enhancedPoseDetection(description?: string): PersonInfo[] {\n // Enhanced pose detection based on scene description\n if (!description) {\n return [];\n }\n\n const people: PersonInfo[] = [];\n const descLower = description.toLowerCase();\n\n // Extract people count and descriptions\n const peopleMatch = description.match(\n /(\\d+)?\\s*(person|people|man|men|woman|women|child|children)/gi\n );\n if (!peopleMatch) {\n return [];\n }\n\n const count = peopleMatch[0].match(/\\d+/)?.[0]\n ? parseInt(peopleMatch[0].match(/\\d+/)?.[0], 10)\n : 1;\n\n // Analyze description for pose and facing information\n const poseKeywords = {\n standing: [\"standing\", \"stand\", \"upright\"],\n sitting: [\"sitting\", \"seated\", \"sit\", \"chair\"],\n walking: [\"walking\", \"walk\", \"moving\"],\n lying: [\"lying\", \"laying\", \"reclined\"],\n };\n\n const facingKeywords = {\n camera: [\"facing camera\", \"looking at camera\", \"facing forward\", \"front view\"],\n away: [\"back to camera\", \"facing away\", \"back view\"],\n left: [\"facing left\", \"profile left\", \"left side\"],\n right: [\"facing right\", \"profile right\", \"right side\"],\n };\n\n let detectedPose = \"standing\";\n let detectedFacing = \"camera\";\n\n // Detect pose\n for (const [pose, keywords] of Object.entries(poseKeywords)) {\n if (keywords.some((kw) => descLower.includes(kw))) {\n detectedPose = pose;\n break;\n }\n }\n\n // Detect facing\n for (const [facing, keywords] of Object.entries(facingKeywords)) {\n if (keywords.some((kw) => descLower.includes(kw))) {\n detectedFacing = facing;\n break;\n }\n }\n\n // Create PersonInfo for each detected person\n for (let i = 0; i < count; i++) {\n const boundingBox = this.generatePlausibleBoundingBox(\"person\", i, count);\n\n people.push({\n id: `person-${Date.now()}-${i}`,\n boundingBox,\n pose: detectedPose as \"sitting\" | \"standing\" | \"lying\" | \"unknown\",\n facing: detectedFacing as \"camera\" | \"away\" | \"left\" | \"right\",\n confidence: 0.85,\n keypoints: this.generatePlausibleKeypoints(\n boundingBox,\n detectedPose as Pose,\n detectedFacing\n ).map((kp) => ({\n part: kp.name,\n position: { x: kp.x, y: kp.y },\n score: kp.score,\n })),\n });\n }\n\n return people;\n }\n\n private generatePlausibleKeypoints(\n boundingBox: { x: number; y: number; width: number; height: number },\n pose: Pose,\n _facing: string\n ): PoseLandmark[] {\n // Generate plausible keypoints based on pose and facing\n const { x, y, width, height } = boundingBox;\n const centerX = x + width / 2;\n\n const keypoints: PoseLandmark[] = [];\n\n // Basic keypoint positions relative to bounding box\n const positions = {\n nose: { x: centerX, y: y + height * 0.1 },\n leftEye: { x: centerX - width * 0.1, y: y + height * 0.08 },\n rightEye: { x: centerX + width * 0.1, y: y + height * 0.08 },\n leftEar: { x: centerX - width * 0.15, y: y + height * 0.1 },\n rightEar: { x: centerX + width * 0.15, y: y + height * 0.1 },\n leftShoulder: { x: centerX - width * 0.25, y: y + height * 0.25 },\n rightShoulder: { x: centerX + width * 0.25, y: y + height * 0.25 },\n leftElbow: { x: centerX - width * 0.3, y: y + height * 0.4 },\n rightElbow: { x: centerX + width * 0.3, y: y + height * 0.4 },\n leftWrist: { x: centerX - width * 0.25, y: y + height * 0.55 },\n rightWrist: { x: centerX + width * 0.25, y: y + height * 0.55 },\n leftHip: { x: centerX - width * 0.15, y: y + height * 0.5 },\n rightHip: { x: centerX + width * 0.15, y: y + height * 0.5 },\n leftKnee: { x: centerX - width * 0.15, y: y + height * 0.7 },\n rightKnee: { x: centerX + width * 0.15, y: y + height * 0.7 },\n leftAnkle: { x: centerX - width * 0.15, y: y + height * 0.9 },\n rightAnkle: { x: centerX + width * 0.15, y: y + height * 0.9 },\n };\n\n // Adjust positions based on pose\n if (pose === \"sitting\") {\n // Lower hips and knees for sitting pose\n positions.leftHip.y += height * 0.1;\n positions.rightHip.y += height * 0.1;\n positions.leftKnee.y -= height * 0.1;\n positions.rightKnee.y -= height * 0.1;\n }\n\n // Convert to PoseLandmark format\n Object.entries(positions).forEach(([name, pos]) => {\n keypoints.push({\n name: name as string,\n x: pos.x,\n y: pos.y,\n score: 0.85,\n });\n });\n\n return keypoints;\n }\n\n convertPosesToPersonInfo(poses: Array<{ keypoints: Array<{ name?: string; x: number; y: number; score?: number }>; score?: number }>): PersonInfo[] {\n return poses.map((pose, index) => {\n const keypoints = pose.keypoints;\n\n // Calculate bounding box from keypoints\n const xs = keypoints.map((kp) => kp.x);\n const ys = keypoints.map((kp) => kp.y);\n const minX = Math.min(...xs);\n const maxX = Math.max(...xs);\n const minY = Math.min(...ys);\n const maxY = Math.max(...ys);\n\n const boundingBox = {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY,\n };\n\n // Determine pose from keypoints\n const detectedPose = this.determinePoseFromKeypoints(keypoints);\n\n // Determine facing direction\n const facing = this.determineFacingDirection(keypoints);\n\n // Convert keypoints to our format\n const convertedKeypoints = keypoints.map((kp) => ({\n part: kp.name || \"unknown\",\n position: { x: kp.x, y: kp.y },\n score: kp.score || 0,\n }));\n\n return {\n id: `person-${Date.now()}-${index}`,\n boundingBox,\n pose: detectedPose as \"sitting\" | \"standing\" | \"lying\" | \"unknown\",\n facing,\n confidence: pose.score || 0.5,\n keypoints: convertedKeypoints,\n };\n });\n }\n\n private determinePoseFromKeypoints(keypoints: Array<{ name?: string; x: number; y: number; score?: number }>): Pose {\n // Simple heuristic to determine pose\n const leftHip = keypoints.find((kp) => kp.name === \"left_hip\");\n const rightHip = keypoints.find((kp) => kp.name === \"right_hip\");\n const leftKnee = keypoints.find((kp) => kp.name === \"left_knee\");\n const rightKnee = keypoints.find((kp) => kp.name === \"right_knee\");\n const leftShoulder = keypoints.find((kp) => kp.name === \"left_shoulder\");\n const rightShoulder = keypoints.find((kp) => kp.name === \"right_shoulder\");\n\n if (!leftHip || !rightHip || !leftKnee || !rightKnee) {\n return \"unknown\";\n }\n\n const hipY = (leftHip.y + rightHip.y) / 2;\n const kneeY = (leftKnee.y + rightKnee.y) / 2;\n const shoulderY =\n leftShoulder && rightShoulder ? (leftShoulder.y + rightShoulder.y) / 2 : hipY - 100;\n\n // Check if person is lying down (shoulders and hips at similar height)\n if (Math.abs(shoulderY - hipY) < 50) {\n return \"lying\";\n }\n\n // Check if person is sitting (knees close to hips)\n if (Math.abs(hipY - kneeY) < 100) {\n return \"sitting\";\n }\n\n // Otherwise assume standing\n return \"standing\";\n }\n\n private determineFacingDirection(\n keypoints: Array<{ name?: string; x: number; y: number; score?: number }>\n ): \"camera\" | \"away\" | \"left\" | \"right\" {\n const leftShoulder = keypoints.find((kp) => kp.name === \"left_shoulder\");\n const rightShoulder = keypoints.find((kp) => kp.name === \"right_shoulder\");\n const nose = keypoints.find((kp) => kp.name === \"nose\");\n\n if (!leftShoulder || !rightShoulder || !nose) {\n return \"camera\"; // Default\n }\n\n const shoulderWidth = Math.abs(rightShoulder.x - leftShoulder.x);\n const shoulderMidpoint = (leftShoulder.x + rightShoulder.x) / 2;\n const noseOffset = nose.x - shoulderMidpoint;\n\n // If shoulders are narrow, person is likely in profile\n if (shoulderWidth < 50) {\n return noseOffset > 0 ? \"right\" : \"left\";\n }\n\n // If nose is significantly offset from shoulder midpoint, person is turning\n if (Math.abs(noseOffset) > shoulderWidth * 0.3) {\n return noseOffset > 0 ? \"right\" : \"left\";\n }\n\n // Check if both ears are visible (facing camera) or not (facing away)\n const leftEar = keypoints.find((kp) => kp.name === \"left_ear\");\n const rightEar = keypoints.find((kp) => kp.name === \"right_ear\");\n\n if (leftEar && rightEar && leftEar.score && rightEar.score) {\n if (leftEar.score > 0.5 && rightEar.score > 0.5) {\n return \"camera\";\n }\n }\n\n return \"camera\"; // Default\n }\n\n async dispose(): Promise<void> {\n if (this.objectDetectionModel) {\n // COCO-SSD doesn't have a dispose method, but we can clear the reference\n this.objectDetectionModel = null;\n }\n\n if (this.poseDetector) {\n this.poseDetector.dispose();\n this.poseDetector = null;\n }\n\n this.initialized = false;\n logger.info(\"[VisionModels] Models disposed\");\n }\n}\n",
19
- "import * as path from \"node:path\";\nimport { TextDecoder } from \"node:util\";\nimport { Worker } from \"node:worker_threads\";\nimport { logger } from \"@elizaos/core\";\nimport type {\n EnhancedSceneDescription,\n Florence2Result,\n OCRResult,\n ScreenCapture,\n VisionConfig,\n} from \"./types\";\n\ninterface WorkerStats {\n fps: number;\n frameCount: number;\n lastUpdate: number;\n}\n\nexport class VisionWorkerManager {\n private config: VisionConfig;\n\n // Workers\n private screenCaptureWorker: Worker | null = null;\n private florence2Worker: Worker | null = null;\n private ocrWorker: Worker | null = null;\n\n // Shared buffers\n private screenBuffer: SharedArrayBuffer;\n private florence2ResultsBuffer: SharedArrayBuffer;\n private ocrResultsBuffer: SharedArrayBuffer;\n\n // Buffer views\n private screenAtomicState: Int32Array;\n private florence2ResultsView: DataView;\n private ocrResultsView: DataView;\n\n // Buffer sizes\n private readonly SCREEN_BUFFER_SIZE = 50 * 1024 * 1024; // 50MB for 4K screen\n private readonly FLORENCE2_RESULTS_SIZE = 10 * 1024 * 1024; // 10MB for results\n private readonly OCR_RESULTS_SIZE = 5 * 1024 * 1024; // 5MB for OCR text\n\n // Atomic indices\n private readonly FRAME_ID_INDEX = 0;\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\n // Worker stats\n private workerStats = new Map<string, WorkerStats>();\n\n // Latest processed data cache\n private latestScreenCapture: ScreenCapture | null = null;\n private latestFlorence2Results = new Map<string, Florence2Result>();\n private latestOCRResult: OCRResult | null = null;\n private lastProcessedFrameId = -1;\n\n // Worker restart tracking\n private restartAttempts = new Map<string, number>();\n private readonly MAX_RESTART_ATTEMPTS = 3;\n\n constructor(config: VisionConfig) {\n this.config = config;\n\n // Initialize shared buffers\n this.screenBuffer = new SharedArrayBuffer(this.SCREEN_BUFFER_SIZE);\n this.florence2ResultsBuffer = new SharedArrayBuffer(this.FLORENCE2_RESULTS_SIZE);\n this.ocrResultsBuffer = new SharedArrayBuffer(this.OCR_RESULTS_SIZE);\n\n // Create views\n this.screenAtomicState = new Int32Array(this.screenBuffer, 0, 6);\n this.florence2ResultsView = new DataView(this.florence2ResultsBuffer);\n this.ocrResultsView = new DataView(this.ocrResultsBuffer);\n }\n\n async initialize(): Promise<void> {\n logger.info(\"[VisionWorkerManager] Initializing worker threads...\");\n\n try {\n // Start screen capture worker\n await this.startScreenCaptureWorker();\n\n // Start Florence-2 worker if enabled\n if (this.config.florence2Enabled) {\n await this.startFlorence2Worker();\n }\n\n // Start OCR worker if enabled\n if (this.config.ocrEnabled) {\n await this.startOCRWorker();\n }\n\n logger.info(\"[VisionWorkerManager] All workers initialized\");\n } catch (error) {\n logger.error(\"[VisionWorkerManager] Failed to initialize workers:\", error);\n throw error;\n }\n }\n\n private async startScreenCaptureWorker(): Promise<void> {\n const workerPath = path.join(__dirname, \"workers\", \"screen-capture-worker.js\");\n\n this.screenCaptureWorker = new Worker(workerPath, {\n workerData: {\n config: {\n displayIndex: this.config.displayIndex,\n captureAllDisplays: this.config.captureAllDisplays,\n targetFPS: this.config.targetScreenFPS,\n sharedBufferSize: this.SCREEN_BUFFER_SIZE,\n },\n sharedBuffer: this.screenBuffer,\n },\n });\n\n this.screenCaptureWorker.on(\"message\", (msg) => {\n if (msg.type === \"fps\") {\n this.workerStats.set(\"screenCapture\", {\n fps: msg.fps,\n frameCount: msg.frameCount,\n lastUpdate: Date.now(),\n });\n } else if (msg.type === \"error\") {\n logger.error(\"[ScreenCaptureWorker] Error:\", msg.error);\n } else if (msg.type === \"log\") {\n // Handle worker log messages\n this.handleWorkerLog(\"ScreenCaptureWorker\", msg);\n }\n });\n\n this.screenCaptureWorker.on(\"error\", (error) => {\n logger.error(\n \"[ScreenCaptureWorker] Worker error:\",\n error instanceof Error ? error.message : String(error)\n );\n // Attempt to restart worker after error\n setTimeout(() => this.restartScreenCaptureWorker(), 1000);\n });\n\n this.screenCaptureWorker.on(\"exit\", (code) => {\n if (code !== 0) {\n logger.error(`[ScreenCaptureWorker] Worker stopped with exit code ${code}`);\n // Attempt to restart worker after crash\n setTimeout(() => this.restartScreenCaptureWorker(), 1000);\n }\n });\n }\n\n private async startFlorence2Worker(): Promise<void> {\n const workerPath = path.join(__dirname, \"workers\", \"florence2-worker.js\");\n\n // Calculate priority tiles (center tiles)\n const priorityTiles: number[] = [];\n const tileSize = this.config.tileSize || 256;\n const estimatedCols = Math.ceil(1920 / tileSize); // Estimate based on common resolution\n const centerRow = Math.floor(estimatedCols / 2);\n const centerCol = Math.floor(estimatedCols / 2);\n\n // Add center and adjacent tiles as priority\n for (let r = centerRow - 1; r <= centerRow + 1; r++) {\n for (let c = centerCol - 1; c <= centerCol + 1; c++) {\n if (r >= 0 && c >= 0) {\n priorityTiles.push(r * estimatedCols + c);\n }\n }\n }\n\n this.florence2Worker = new Worker(workerPath, {\n workerData: {\n config: {\n tileSize: this.config.tileSize || 256,\n priorityTiles,\n },\n sharedBuffer: this.screenBuffer,\n resultsBuffer: this.florence2ResultsBuffer,\n },\n });\n\n this.florence2Worker.on(\"message\", (msg) => {\n if (msg.type === \"fps\") {\n this.workerStats.set(\"florence2\", {\n fps: msg.fps,\n frameCount: msg.frameCount,\n lastUpdate: Date.now(),\n });\n } else if (msg.type === \"tile_analyzed\") {\n // Update latest results cache\n this.updateFlorence2Cache(msg);\n } else if (msg.type === \"error\") {\n logger.error(\"[Florence2Worker] Error:\", msg.error);\n } else if (msg.type === \"log\") {\n // Handle worker log messages\n this.handleWorkerLog(\"Florence2Worker\", msg);\n }\n });\n\n this.florence2Worker.on(\"error\", (error) => {\n logger.error(\n \"[Florence2Worker] Worker error:\",\n error instanceof Error ? error.message : String(error)\n );\n // Attempt to restart worker after error\n setTimeout(() => this.restartFlorence2Worker(), 1000);\n });\n\n this.florence2Worker.on(\"exit\", (code) => {\n if (code !== 0) {\n logger.error(`[Florence2Worker] Worker stopped with exit code ${code}`);\n // Attempt to restart worker after crash\n setTimeout(() => this.restartFlorence2Worker(), 1000);\n }\n });\n }\n\n private async startOCRWorker(): Promise<void> {\n const workerPath = path.join(__dirname, \"workers\", \"ocr-worker.js\");\n\n this.ocrWorker = new Worker(workerPath, {\n workerData: {\n config: {\n processFullScreen: true,\n tileSize: this.config.tileSize || 256,\n textRegions: this.config.textRegions,\n },\n sharedBuffer: this.screenBuffer,\n resultsBuffer: this.ocrResultsBuffer,\n },\n });\n\n this.ocrWorker.on(\"message\", (msg) => {\n if (msg.type === \"fps\") {\n this.workerStats.set(\"ocr\", {\n fps: msg.fps,\n frameCount: msg.frameCount,\n lastUpdate: Date.now(),\n });\n } else if (msg.type === \"ocr_complete\") {\n // Update latest OCR cache\n this.updateOCRCache(msg);\n } else if (msg.type === \"error\") {\n logger.error(\"[OCRWorker] Error:\", msg.error);\n } else if (msg.type === \"log\") {\n // Handle worker log messages\n this.handleWorkerLog(\"OCRWorker\", msg);\n }\n });\n\n this.ocrWorker.on(\"error\", (error) => {\n logger.error(\n \"[OCRWorker] Worker error:\",\n error instanceof Error ? error.message : String(error)\n );\n // Attempt to restart worker after error\n setTimeout(() => this.restartOCRWorker(), 1000);\n });\n\n this.ocrWorker.on(\"exit\", (code) => {\n if (code !== 0) {\n logger.error(`[OCRWorker] Worker stopped with exit code ${code}`);\n // Attempt to restart worker after crash\n setTimeout(() => this.restartOCRWorker(), 1000);\n }\n });\n }\n\n private updateFlorence2Cache(msg: { tileId: string }): void {\n // Read result from shared buffer\n try {\n const tileId = msg.tileId;\n const result = this.readFlorence2Result(tileId);\n if (result) {\n this.latestFlorence2Results.set(tileId, result);\n }\n } catch (error) {\n logger.error(\"[VisionWorkerManager] Failed to update Florence2 cache:\", error);\n }\n }\n\n private updateOCRCache(_msg: unknown): void {\n // Read OCR result from shared buffer\n try {\n const result = this.readOCRResult();\n if (result) {\n this.latestOCRResult = result;\n }\n } catch (error) {\n logger.error(\"[VisionWorkerManager] Failed to update OCR cache:\", error);\n }\n }\n\n private readFlorence2Result(tileId: string): Florence2Result | null {\n try {\n // Calculate tile index from ID\n const match = tileId.match(/tile-(\\d+)-(\\d+)/);\n if (!match) {\n return null;\n }\n\n const row = parseInt(match[1], 10);\n const col = parseInt(match[2], 10);\n const tileIndex = row * 10 + col; // Assuming max 10 columns\n\n const RESULTS_HEADER_SIZE = 16;\n const MAX_RESULT_SIZE = 4096;\n const offset = RESULTS_HEADER_SIZE + tileIndex * MAX_RESULT_SIZE;\n\n // Read length\n const length = this.florence2ResultsView.getUint32(offset, true);\n if (length === 0 || length > MAX_RESULT_SIZE - 4) {\n return null;\n }\n\n // Read JSON data\n const bytes = new Uint8Array(length);\n for (let i = 0; i < length; i++) {\n bytes[i] = this.florence2ResultsView.getUint8(offset + 4 + i);\n }\n\n const json = new TextDecoder().decode(bytes);\n return JSON.parse(json);\n } catch (error) {\n logger.error(\"[VisionWorkerManager] Failed to read Florence2 result:\", error);\n return null;\n }\n }\n\n private readOCRResult(): OCRResult | null {\n try {\n const RESULTS_HEADER_SIZE = 16;\n const offset = RESULTS_HEADER_SIZE;\n\n // Read length\n const length = this.ocrResultsView.getUint32(offset, true);\n if (length === 0) {\n return null;\n }\n\n // Read frame ID and timestamp\n const _frameId = this.ocrResultsView.getUint32(offset + 4, true);\n const _timestamp = this.ocrResultsView.getFloat64(offset + 8, true);\n\n // Read JSON data\n const dataOffset = offset + 16;\n const bytes = new Uint8Array(Math.min(length, 65536));\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = this.ocrResultsView.getUint8(dataOffset + i);\n }\n\n const json = new TextDecoder().decode(bytes);\n return JSON.parse(json);\n } catch (error) {\n logger.error(\"[VisionWorkerManager] Failed to read OCR result:\", error);\n return null;\n }\n }\n\n // Public API - Non-blocking access to latest data\n\n getLatestScreenCapture(): ScreenCapture | null {\n // Read current frame metadata\n const frameId = Atomics.load(this.screenAtomicState, this.FRAME_ID_INDEX);\n\n if (frameId <= this.lastProcessedFrameId) {\n return this.latestScreenCapture;\n }\n\n try {\n const width = Atomics.load(this.screenAtomicState, this.WIDTH_INDEX);\n const height = Atomics.load(this.screenAtomicState, this.HEIGHT_INDEX);\n const _displayIndex = Atomics.load(this.screenAtomicState, this.DISPLAY_INDEX);\n const timestamp = Atomics.load(this.screenAtomicState, this.TIMESTAMP_INDEX);\n\n // Create screen capture object\n this.latestScreenCapture = {\n timestamp,\n width,\n height,\n data: Buffer.alloc(0), // We don't copy the full data for performance\n tiles: this.generateTiles(width, height),\n };\n\n this.lastProcessedFrameId = frameId;\n } catch (error) {\n logger.error(\"[VisionWorkerManager] Failed to read screen capture:\", error);\n }\n\n return this.latestScreenCapture;\n }\n\n getLatestEnhancedScene(): EnhancedSceneDescription {\n const screenCapture = this.getLatestScreenCapture();\n\n // Combine all Florence-2 results\n const florence2Captions: string[] = [];\n const allObjects: Array<{\n label: string;\n confidence: number;\n bbox: { x: number; y: number; width: number; height: number };\n }> = [];\n const allTags = new Set<string>();\n\n this.latestFlorence2Results.forEach((result) => {\n if (result.caption) {\n florence2Captions.push(result.caption);\n }\n if (result.objects) {\n allObjects.push(...result.objects);\n }\n if (result.tags) {\n for (const tag of result.tags) {\n allTags.add(tag);\n }\n }\n });\n\n const _tiles = this.generateTiles(screenCapture?.width || 0, screenCapture?.height || 0);\n\n // Map allObjects to DetectedObject format\n const mappedObjects = allObjects.map((obj, index) => ({\n id: `obj-${index}`,\n type: obj.label,\n confidence: obj.confidence,\n boundingBox: obj.bbox,\n }));\n\n return {\n timestamp: Date.now(),\n description: florence2Captions.join(\". \"),\n objects: mappedObjects,\n people: [], // Could be populated by TensorFlow worker\n sceneChanged: true,\n changePercentage: 100,\n screenCapture: this.latestScreenCapture || undefined,\n screenAnalysis: {\n fullScreenOCR: this.latestOCRResult?.fullText,\n activeTile: {\n timestamp: Date.now(),\n florence2: this.latestFlorence2Results.values().next().value,\n ocr: this.latestOCRResult || undefined,\n },\n gridSummary: `${screenCapture?.tiles.length || 0} tiles analyzed`,\n uiElements: allObjects.map((obj) => ({\n type: obj.label,\n text: \"\",\n position: obj.bbox,\n })),\n },\n };\n }\n\n private generateTiles(\n width: number,\n height: number\n ): Array<{\n id: string;\n row: number;\n col: number;\n x: number;\n y: number;\n width: number;\n height: number;\n }> {\n const tileSize = this.config.tileSize || 256;\n const tiles: Array<{\n id: string;\n row: number;\n col: number;\n x: number;\n y: number;\n width: number;\n height: number;\n }> = [];\n\n for (let row = 0; row < Math.ceil(height / tileSize); row++) {\n for (let col = 0; col < Math.ceil(width / tileSize); col++) {\n const x = col * tileSize;\n const y = row * tileSize;\n tiles.push({\n id: `tile-${row}-${col}`,\n row,\n col,\n x,\n y,\n width: Math.min(tileSize, width - x),\n height: Math.min(tileSize, height - y),\n });\n }\n }\n\n return tiles;\n }\n\n getWorkerStats(): Map<string, WorkerStats> {\n return new Map(this.workerStats);\n }\n\n async setDisplayIndex(index: number): Promise<void> {\n if (this.screenCaptureWorker) {\n this.screenCaptureWorker.postMessage({\n type: \"set_display\",\n displayIndex: index,\n });\n }\n }\n\n async setTextRegions(\n regions: Array<{ x: number; y: number; width: number; height: number }>\n ): Promise<void> {\n if (this.ocrWorker) {\n this.ocrWorker.postMessage({\n type: \"update_regions\",\n regions,\n });\n }\n }\n\n async stop(): Promise<void> {\n logger.info(\"[VisionWorkerManager] Stopping all workers...\");\n\n const stopPromises: Promise<void>[] = [];\n\n if (this.screenCaptureWorker) {\n stopPromises.push(\n new Promise((resolve) => {\n this.screenCaptureWorker?.once(\"exit\", () => resolve());\n this.screenCaptureWorker?.postMessage({ type: \"stop\" });\n })\n );\n }\n\n if (this.florence2Worker) {\n stopPromises.push(\n new Promise((resolve) => {\n this.florence2Worker?.once(\"exit\", () => resolve());\n this.florence2Worker?.postMessage({ type: \"stop\" });\n })\n );\n }\n\n if (this.ocrWorker) {\n stopPromises.push(\n new Promise((resolve) => {\n this.ocrWorker?.once(\"exit\", () => resolve());\n this.ocrWorker?.postMessage({ type: \"stop\" });\n })\n );\n }\n\n await Promise.all(stopPromises);\n logger.info(\"[VisionWorkerManager] All workers stopped\");\n }\n\n private handleWorkerLog(\n workerName: string,\n msg: { level: string; message: string; args: unknown[] }\n ): void {\n const { level, message, args } = msg;\n const formattedMessage = `[${workerName}] ${message}`;\n const stringArgs = args.map((arg) => String(arg));\n\n switch (level) {\n case \"info\":\n logger.info(formattedMessage, ...stringArgs);\n break;\n case \"warn\":\n logger.warn(formattedMessage, ...stringArgs);\n break;\n case \"error\":\n logger.error(formattedMessage, ...stringArgs);\n break;\n case \"debug\":\n logger.debug(formattedMessage, ...stringArgs);\n break;\n }\n }\n\n private async restartScreenCaptureWorker(): Promise<void> {\n const attempts = this.restartAttempts.get(\"screenCapture\") || 0;\n\n if (attempts >= this.MAX_RESTART_ATTEMPTS) {\n logger.error(\"[VisionWorkerManager] Max restart attempts reached for screen capture worker\");\n return;\n }\n\n this.restartAttempts.set(\"screenCapture\", attempts + 1);\n logger.info(`[VisionWorkerManager] Restarting screen capture worker (attempt ${attempts + 1})`);\n\n try {\n // Clean up existing worker\n if (this.screenCaptureWorker) {\n this.screenCaptureWorker.removeAllListeners();\n this.screenCaptureWorker = null;\n }\n\n // Start new worker\n await this.startScreenCaptureWorker();\n\n // Reset restart counter on successful start\n this.restartAttempts.set(\"screenCapture\", 0);\n } catch (error) {\n logger.error(\"[VisionWorkerManager] Failed to restart screen capture worker:\", error);\n }\n }\n\n private async restartFlorence2Worker(): Promise<void> {\n const attempts = this.restartAttempts.get(\"florence2\") || 0;\n\n if (attempts >= this.MAX_RESTART_ATTEMPTS) {\n logger.error(\"[VisionWorkerManager] Max restart attempts reached for Florence2 worker\");\n return;\n }\n\n this.restartAttempts.set(\"florence2\", attempts + 1);\n logger.info(`[VisionWorkerManager] Restarting Florence2 worker (attempt ${attempts + 1})`);\n\n try {\n // Clean up existing worker\n if (this.florence2Worker) {\n this.florence2Worker.removeAllListeners();\n this.florence2Worker = null;\n }\n\n // Start new worker\n await this.startFlorence2Worker();\n\n // Reset restart counter on successful start\n this.restartAttempts.set(\"florence2\", 0);\n } catch (error) {\n logger.error(\"[VisionWorkerManager] Failed to restart Florence2 worker:\", error);\n }\n }\n\n private async restartOCRWorker(): Promise<void> {\n const attempts = this.restartAttempts.get(\"ocr\") || 0;\n\n if (attempts >= this.MAX_RESTART_ATTEMPTS) {\n logger.error(\"[VisionWorkerManager] Max restart attempts reached for OCR worker\");\n return;\n }\n\n this.restartAttempts.set(\"ocr\", attempts + 1);\n logger.info(`[VisionWorkerManager] Restarting OCR worker (attempt ${attempts + 1})`);\n\n try {\n // Clean up existing worker\n if (this.ocrWorker) {\n this.ocrWorker.removeAllListeners();\n this.ocrWorker = null;\n }\n\n // Start new worker\n await this.startOCRWorker();\n\n // Reset restart counter on successful start\n this.restartAttempts.set(\"ocr\", 0);\n } catch (error) {\n logger.error(\"[VisionWorkerManager] Failed to restart OCR worker:\", error);\n }\n }\n}\n",
20
- "import type { IAgentRuntime, Memory } from \"@elizaos/core\";\nimport { createUniqueUuid } from \"@elizaos/core\";\nimport { setVisionModeAction } from \"../../action\";\nimport type { VisionService } from \"../../service\";\nimport { VisionMode } from \"../../types\";\n\nexport class ScreenVisionE2ETestSuite {\n name = \"plugin-vision-screen-e2e\";\n description = \"E2E tests for screen vision functionality including Florence-2 and OCR\";\n\n tests = [\n {\n name: \"Should initialize screen vision components\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing screen vision initialization...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n // Set vision mode to SCREEN\n await visionService.setVisionMode(VisionMode.SCREEN);\n\n // Wait for initialization\n await new Promise((resolve) => setTimeout(resolve, 2000));\n\n const mode = visionService.getVisionMode();\n if (mode !== VisionMode.SCREEN) {\n throw new Error(`Expected vision mode SCREEN but got ${mode}`);\n }\n\n console.log(\"✓ Screen vision mode activated\");\n\n // Check if screen capture is available\n const screenInfo = await visionService.getScreenCapture();\n if (screenInfo) {\n console.log(`✓ Screen capture available: ${screenInfo.width}x${screenInfo.height}`);\n } else {\n console.log(\"⚠️ Screen capture not yet available (may still be initializing)\");\n }\n },\n },\n\n {\n name: \"Should capture and tile screen\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing screen capture and tiling...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n // Ensure screen mode is active\n await visionService.setVisionMode(VisionMode.SCREEN);\n\n // Wait for capture\n await new Promise((resolve) => setTimeout(resolve, 3000));\n\n const screenCapture = await visionService.getScreenCapture();\n if (!screenCapture) {\n console.warn(\n \"⚠️ No screen capture available - screen capture may not be supported in this environment\"\n );\n return;\n }\n\n console.log(`✓ Screen captured: ${screenCapture.width}x${screenCapture.height}`);\n console.log(`✓ Divided into ${screenCapture.tiles.length} tiles`);\n\n // Check tile structure\n const firstTile = screenCapture.tiles[0];\n if (!firstTile) {\n throw new Error(\"No tiles created from screen capture\");\n }\n\n console.log(` First tile: ${firstTile.id} at (${firstTile.x}, ${firstTile.y})`);\n console.log(` Tile size: ${firstTile.width}x${firstTile.height}`);\n\n // Check if priority tiles have data\n const tilesWithData = screenCapture.tiles.filter((t) => t.data !== undefined);\n console.log(` Tiles with data: ${tilesWithData.length}`);\n\n if (tilesWithData.length === 0) {\n console.warn(\"⚠️ No tiles have been processed yet\");\n }\n },\n },\n\n {\n name: \"Should analyze screen content with Florence-2 and OCR\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing screen content analysis...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n // Ensure screen mode is active\n await visionService.setVisionMode(VisionMode.SCREEN);\n\n // Wait for analysis\n await new Promise((resolve) => setTimeout(resolve, 5000));\n\n const enhancedScene = await visionService.getEnhancedSceneDescription();\n if (!enhancedScene || !enhancedScene.screenAnalysis) {\n console.warn(\"⚠️ No enhanced scene analysis available yet\");\n return;\n }\n\n console.log(\"✓ Enhanced scene analysis available\");\n\n const screenAnalysis = enhancedScene.screenAnalysis;\n\n // Check active tile analysis\n if (screenAnalysis.activeTile) {\n console.log(\"✓ Active tile analyzed\");\n\n if (screenAnalysis.activeTile.florence2) {\n console.log(` Florence-2 caption: ${screenAnalysis.activeTile.florence2.caption}`);\n console.log(\n ` Objects detected: ${screenAnalysis.activeTile.florence2.objects?.length || 0}`\n );\n console.log(\n ` Tags: ${screenAnalysis.activeTile.florence2.tags?.join(\", \") || \"none\"}`\n );\n }\n\n if (screenAnalysis.activeTile.ocr) {\n console.log(` OCR text blocks: ${screenAnalysis.activeTile.ocr.blocks.length}`);\n console.log(\n ` OCR preview: \"${screenAnalysis.activeTile.ocr.fullText.substring(0, 50)}...\"`\n );\n }\n }\n\n // Check full screen OCR\n if (screenAnalysis.fullScreenOCR) {\n console.log(`✓ Full screen OCR: ${screenAnalysis.fullScreenOCR.length} characters`);\n }\n\n // Check UI elements\n if (screenAnalysis.uiElements && screenAnalysis.uiElements.length > 0) {\n console.log(`✓ UI elements detected: ${screenAnalysis.uiElements.length}`);\n const elementTypes = screenAnalysis.uiElements.map((e) => e.type);\n const uniqueTypes = [...new Set(elementTypes)];\n console.log(` Types: ${uniqueTypes.join(\", \")}`);\n }\n },\n },\n\n {\n name: \"Should switch between vision modes\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing vision mode switching...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n // Test all modes\n const modes = [VisionMode.CAMERA, VisionMode.SCREEN, VisionMode.BOTH, VisionMode.OFF];\n\n for (const mode of modes) {\n console.log(` Switching to ${mode} mode...`);\n await visionService.setVisionMode(mode);\n\n // Wait for mode switch\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n const currentMode = visionService.getVisionMode();\n if (currentMode !== mode) {\n throw new Error(`Failed to switch to ${mode} mode, current mode is ${currentMode}`);\n }\n\n console.log(` ✓ Successfully switched to ${mode} mode`);\n }\n\n // Test with action\n console.log(\" Testing SET_VISION_MODE action...\");\n\n const message: Memory = {\n id: createUniqueUuid(runtime, \"test-msg\"),\n entityId: runtime.agentId,\n content: { text: \"set vision mode to both\" },\n agentId: runtime.agentId,\n roomId: createUniqueUuid(runtime, \"test-room\"),\n createdAt: Date.now(),\n };\n\n let callbackCalled = false;\n await setVisionModeAction.handler(\n runtime,\n message,\n { values: {}, data: {}, text: \"\" },\n {},\n async (response) => {\n callbackCalled = true;\n console.log(` Action response: ${response.text}`);\n return [];\n }\n );\n\n if (!callbackCalled) {\n throw new Error(\"SET_VISION_MODE action did not call callback\");\n }\n\n const finalMode = visionService.getVisionMode();\n if (finalMode !== VisionMode.BOTH) {\n throw new Error(`SET_VISION_MODE action failed, mode is ${finalMode}`);\n }\n\n console.log(\"✓ Vision mode switching works correctly\");\n },\n },\n\n {\n name: \"Should provide combined vision data in BOTH mode\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing combined camera and screen vision...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n // Set to BOTH mode\n await visionService.setVisionMode(VisionMode.BOTH);\n\n // Wait for both systems to initialize\n await new Promise((resolve) => setTimeout(resolve, 5000));\n\n const enhancedScene = await visionService.getEnhancedSceneDescription();\n const hasCamera = visionService.getCameraInfo() !== null;\n const hasScreen = (await visionService.getScreenCapture()) !== null;\n\n console.log(` Camera available: ${hasCamera}`);\n console.log(` Screen capture available: ${hasScreen}`);\n\n if (!hasCamera && !hasScreen) {\n console.warn(\"⚠️ Neither camera nor screen capture available in this environment\");\n return;\n }\n\n if (enhancedScene) {\n // Check for camera data\n if (hasCamera && enhancedScene.description) {\n console.log(\"✓ Camera data present in combined mode\");\n console.log(` Scene: ${enhancedScene.description.substring(0, 50)}...`);\n }\n\n // Check for screen data\n if (hasScreen && enhancedScene.screenAnalysis) {\n console.log(\"✓ Screen data present in combined mode\");\n console.log(` Grid: ${enhancedScene.screenAnalysis.gridSummary}`);\n }\n }\n\n // Check provider output\n const state = await runtime.composeState({\n id: createUniqueUuid(runtime, \"test-msg\"),\n entityId: runtime.agentId,\n content: { text: \"test\" },\n agentId: runtime.agentId,\n roomId: createUniqueUuid(runtime, \"test-room\"),\n createdAt: Date.now(),\n });\n\n if (state.text.includes(\"Vision mode: BOTH\")) {\n console.log(\"✓ Provider correctly reports BOTH mode\");\n }\n },\n },\n\n {\n name: \"Should handle screen capture errors gracefully\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing error handling...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n // Try to set invalid region (should handle gracefully)\n // Access private property for testing purposes\n const testableService = visionService as unknown as {\n visionConfig: { screenRegion?: { x: number; y: number; width: number; height: number } };\n };\n const originalConfig = testableService.visionConfig;\n testableService.visionConfig.screenRegion = {\n x: -100,\n y: -100,\n width: 50000,\n height: 50000,\n };\n\n await visionService.setVisionMode(VisionMode.SCREEN);\n await new Promise((resolve) => setTimeout(resolve, 2000));\n\n // Service should still be active despite invalid region\n const isActive = visionService.isActive();\n console.log(` Service active after invalid config: ${isActive}`);\n\n // Restore config\n testableService.visionConfig = originalConfig;\n\n console.log(\"✓ Error handling works correctly\");\n },\n },\n ];\n}\n\nexport default new ScreenVisionE2ETestSuite();\n",
21
- "import type { Content, IAgentRuntime, Memory, ServiceTypeName, State } from \"@elizaos/core\";\nimport { createUniqueUuid } from \"@elizaos/core\";\nimport { captureImageAction, describeSceneAction } from \"../../action\";\nimport type { VisionService } from \"../../service\";\n\nexport class VisionBasicE2ETestSuite {\n name = \"plugin-vision-basic-e2e\";\n description = \"Basic end-to-end tests for vision plugin functionality\";\n\n tests = [\n {\n name: \"Should initialize vision service\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing vision service initialization...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\" as ServiceTypeName);\n if (!visionService) {\n throw new Error(\"Vision service not available - service must be registered\");\n }\n\n // Check if service is active\n const isActive = visionService.isActive();\n\n // Get camera info\n const cameraInfo = visionService.getCameraInfo();\n\n if (!isActive || !cameraInfo) {\n // For CI/CD environments without cameras, check that service at least initializes\n console.warn(\"⚠️ No camera detected. Service initialized but not active.\");\n console.log(\" This is acceptable in CI/CD environments without cameras.\");\n } else {\n console.log(\"✓ Vision service initialized and active\");\n console.log(`✓ Connected to camera: ${cameraInfo.name} (ID: ${cameraInfo.id})`);\n }\n },\n },\n\n {\n name: \"Should describe scene when requested\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing scene description action...\");\n\n const roomId = createUniqueUuid(runtime, \"test-room\");\n const message: Memory = {\n id: createUniqueUuid(runtime, \"test-msg-describe\"),\n entityId: runtime.agentId,\n content: { text: \"what do you see?\" },\n agentId: runtime.agentId,\n roomId,\n createdAt: Date.now(),\n };\n\n let callbackCalled = false;\n let callbackResponse: Content | null = null;\n\n const state: State = { values: {}, data: {}, text: \"\" };\n\n // Get vision service to check if active\n const visionService = runtime.getService<VisionService>(\"VISION\" as ServiceTypeName);\n\n // Validate the action\n const isValid = await describeSceneAction.validate(runtime, message, state);\n\n if (!visionService || !visionService.isActive()) {\n // If vision service is not active, validation should return false\n if (isValid) {\n throw new Error(\n \"Action validation should return false when vision service is not active\"\n );\n }\n console.log(\" Action validation correctly returned false (vision not active)\");\n\n // But handler should still work and provide appropriate message\n await describeSceneAction.handler(runtime, message, state, {}, async (response) => {\n callbackCalled = true;\n callbackResponse = response;\n return [];\n });\n\n if (!callbackCalled) {\n throw new Error(\"Callback was not called - action handler failed\");\n }\n\n if (!callbackResponse || !callbackResponse.text) {\n throw new Error(\"No response text returned from action\");\n }\n\n console.log(\"✓ Scene description action handled unavailability correctly\");\n console.log(` Response: ${callbackResponse.text}`);\n\n // Verify it indicates camera not available\n if (\n !callbackResponse.text.includes(\"cannot see\") &&\n !callbackResponse.text.includes(\"no camera\")\n ) {\n throw new Error(\"Response does not indicate camera unavailability\");\n }\n } else {\n // Vision is active, normal test flow\n if (!isValid) {\n throw new Error(\"describeSceneAction validation failed despite active vision\");\n }\n console.log(\" Action validation: passed\");\n\n await describeSceneAction.handler(runtime, message, state, {}, async (response) => {\n callbackCalled = true;\n callbackResponse = response;\n return [];\n });\n\n if (!callbackCalled) {\n throw new Error(\"Callback was not called - action handler failed\");\n }\n\n if (!callbackResponse || !callbackResponse.text) {\n throw new Error(\"No response text returned from action\");\n }\n\n console.log(\"✓ Scene description action executed\");\n console.log(` Response: ${callbackResponse.text}`);\n if (callbackResponse.thought) {\n console.log(` Thought: ${callbackResponse.thought}`);\n }\n }\n\n // Verify response contains expected action\n if (!callbackResponse.actions || !callbackResponse.actions.includes(\"DESCRIBE_SCENE\")) {\n throw new Error(\"Response does not include DESCRIBE_SCENE action\");\n }\n },\n },\n\n {\n name: \"Should capture image when requested\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing image capture action...\");\n\n const roomId = createUniqueUuid(runtime, \"test-room\");\n const message: Memory = {\n id: createUniqueUuid(runtime, \"test-msg-capture\"),\n entityId: runtime.agentId,\n content: { text: \"take a photo\" },\n agentId: runtime.agentId,\n roomId,\n createdAt: Date.now(),\n };\n\n let callbackCalled = false;\n let callbackResponse: Content | null = null;\n\n const state: State = { values: {}, data: {}, text: \"\" };\n\n // Get vision service to check if active\n const visionService = runtime.getService<VisionService>(\"VISION\" as ServiceTypeName);\n\n // Validate the action\n const isValid = await captureImageAction.validate(runtime, message, state);\n\n if (!visionService || !visionService.isActive()) {\n // If vision service is not active, validation should return false\n if (isValid) {\n throw new Error(\n \"Action validation should return false when vision service is not active\"\n );\n }\n console.log(\" Action validation correctly returned false (vision not active)\");\n\n // But handler should still work and provide appropriate message\n await captureImageAction.handler(runtime, message, state, {}, async (response) => {\n callbackCalled = true;\n callbackResponse = response;\n return [];\n });\n\n if (!callbackCalled) {\n throw new Error(\"Callback was not called - action handler failed\");\n }\n\n if (!callbackResponse || !callbackResponse.text) {\n throw new Error(\"No response text returned from action\");\n }\n\n console.log(\"✓ Image capture action handled unavailability correctly\");\n console.log(` Response: ${callbackResponse.text}`);\n\n // Verify it indicates camera not available\n if (\n !callbackResponse.text.includes(\"cannot capture\") &&\n !callbackResponse.text.includes(\"no camera\")\n ) {\n throw new Error(\"Response does not indicate camera unavailability\");\n }\n } else {\n // Vision is active, normal test flow\n if (!isValid) {\n throw new Error(\"captureImageAction validation failed despite active vision\");\n }\n console.log(\" Action validation: passed\");\n\n await captureImageAction.handler(runtime, message, state, {}, async (response) => {\n callbackCalled = true;\n callbackResponse = response;\n return [];\n });\n\n if (!callbackCalled) {\n throw new Error(\"Callback was not called - action handler failed\");\n }\n\n if (!callbackResponse || !callbackResponse.text) {\n throw new Error(\"No response text returned from action\");\n }\n\n console.log(\"✓ Image capture action executed\");\n console.log(` Response: ${callbackResponse.text}`);\n\n // If camera is active, we should have an attachment\n if (!callbackResponse.attachments || callbackResponse.attachments.length === 0) {\n throw new Error(\"No image attachment returned despite active camera\");\n }\n\n const attachment = callbackResponse.attachments[0];\n if (!attachment.url || !attachment.url.startsWith(\"data:image/\")) {\n throw new Error(\"Invalid image attachment format\");\n }\n\n console.log(` ✓ Image attachment valid: ${attachment.title}`);\n }\n\n // Verify response contains expected action\n if (!callbackResponse.actions || !callbackResponse.actions.includes(\"CAPTURE_IMAGE\")) {\n throw new Error(\"Response does not include CAPTURE_IMAGE action\");\n }\n },\n },\n\n {\n name: \"Should provide vision context through provider\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing vision provider...\");\n\n // Compose state to trigger providers\n const message: Memory = {\n id: createUniqueUuid(runtime, \"test-msg-provider\"),\n entityId: runtime.agentId,\n content: { text: \"test provider\" },\n agentId: runtime.agentId,\n roomId: createUniqueUuid(runtime, \"test-room\"),\n createdAt: Date.now(),\n };\n\n const state = await runtime.composeState(message);\n\n // Vision provider should always add data\n if (state.values.visionAvailable === undefined) {\n throw new Error(\"Vision provider data missing - provider not registered or failed\");\n }\n\n console.log(\"✓ Vision provider data found in state\");\n console.log(` Vision available: ${state.values.visionAvailable}`);\n console.log(` Camera status: ${state.values.cameraStatus}`);\n\n // Verify vision context in formatted text\n if (!state.text.includes(\"Visual Perception\")) {\n throw new Error(\"Vision context not included in state text\");\n }\n console.log(\"✓ Vision context included in state text\");\n\n // If vision is available, verify scene data\n if (state.values.visionAvailable && state.values.sceneDescription) {\n console.log(` Scene description: ${state.values.sceneDescription}`);\n }\n },\n },\n\n {\n name: \"Should handle scene changes efficiently\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing scene change detection...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\" as ServiceTypeName);\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n if (!visionService.isActive()) {\n console.warn(\"⚠️ Vision service not active - skipping scene change test\");\n console.log(\" This is acceptable in environments without cameras\");\n return;\n }\n\n // Get initial scene description\n const initialScene = await visionService.getSceneDescription();\n console.log(` Initial scene: ${initialScene ? \"Available\" : \"Pending...\"}`);\n\n // Wait for scene processing\n await new Promise((resolve) => setTimeout(resolve, 2000));\n\n // Get updated scene description\n const updatedScene = await visionService.getSceneDescription();\n\n if (!updatedScene) {\n throw new Error(\"No scene description available after 2 seconds\");\n }\n\n console.log(\"✓ Scene monitoring active\");\n console.log(` Scene timestamp: ${new Date(updatedScene.timestamp).toISOString()}`);\n console.log(` Description: ${updatedScene.description.substring(0, 100)}...`);\n\n if (updatedScene.changePercentage !== undefined) {\n console.log(` Last change: ${updatedScene.changePercentage.toFixed(1)}%`);\n }\n },\n },\n\n {\n name: \"Should detect objects and people in scene\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing object and person detection...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\" as ServiceTypeName);\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n if (!visionService.isActive()) {\n console.warn(\"⚠️ Vision service not active - skipping detection test\");\n console.log(\" This is acceptable in environments without cameras\");\n return;\n }\n\n // Wait for scene processing to accumulate frames\n console.log(\" Waiting for scene analysis...\");\n await new Promise((resolve) => setTimeout(resolve, 3000));\n\n // Get scene description\n const scene = await visionService.getSceneDescription();\n\n if (!scene) {\n throw new Error(\"No scene description available after 3 seconds\");\n }\n\n console.log(\"✓ Scene analysis complete\");\n console.log(` Description: ${scene.description.substring(0, 100)}...`);\n console.log(` Objects detected: ${scene.objects.length}`);\n console.log(` People detected: ${scene.people.length}`);\n\n // Verify object detection\n if (scene.objects.length > 0) {\n console.log(\" Detected objects:\");\n const objectTypes = scene.objects.reduce(\n (acc, obj) => {\n acc[obj.type] = (acc[obj.type] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>\n );\n\n for (const [type, count] of Object.entries(objectTypes)) {\n console.log(` - ${count} ${type}(s)`);\n }\n\n // Verify objects have required fields\n for (const obj of scene.objects) {\n if (!obj.id || !obj.type || obj.confidence === undefined || !obj.boundingBox) {\n throw new Error(\"Detected object missing required fields\");\n }\n }\n }\n\n // Verify person detection\n if (scene.people.length > 0) {\n console.log(\" Detected people:\");\n for (const person of scene.people) {\n console.log(\n ` - Person ${person.id}: ${person.pose} pose, facing ${person.facing}, confidence ${person.confidence.toFixed(2)}`\n );\n\n // Verify person has required fields\n if (\n !person.id ||\n !person.pose ||\n !person.facing ||\n person.confidence === undefined ||\n !person.boundingBox\n ) {\n throw new Error(\"Detected person missing required fields\");\n }\n }\n }\n\n // If there's motion, we should detect something\n if (scene.changePercentage > 10) {\n console.log(` Scene change: ${scene.changePercentage.toFixed(1)}%`);\n if (scene.objects.length === 0 && scene.people.length === 0) {\n console.warn(\" ⚠️ Significant scene change but no objects/people detected\");\n console.log(\" This might indicate the motion detection threshold needs adjustment\");\n }\n }\n },\n },\n ];\n}\n\nexport default new VisionBasicE2ETestSuite();\n",
22
- "import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport type { IAgentRuntime } from \"@elizaos/core\";\nimport type { VisionService } from \"../../service\";\n\n/** A single vision capture entry (success or error) */\ninterface VisionCaptureEntry {\n index: number;\n timestamp: string;\n timestampMs?: number;\n elapsedMs?: number;\n scene?: {\n description: string;\n changePercentage: number;\n sceneChanged: boolean;\n objectCount: number;\n peopleCount: number;\n objects: { type: string }[];\n people: { pose: string }[];\n } | null;\n frame?: {\n width: number;\n height: number;\n format: string;\n timestamp: number;\n } | null;\n imageBase64?: string | null;\n error?: string;\n}\n\nexport class VisionCaptureLogTestSuite {\n name = \"plugin-vision-capture-log\";\n description = \"Captures 30 seconds of vision data and saves to logs for analysis\";\n\n tests = [\n {\n name: \"Should capture and log 30 seconds of vision data\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Starting 30-second vision capture test...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n if (!visionService.isActive()) {\n console.warn(\"⚠️ Vision service not active - no camera available\");\n console.log(\" Cannot capture vision data without a camera\");\n return;\n }\n\n // Create logs directory if it doesn't exist\n const logsDir = path.join(process.cwd(), \"logs\");\n const sessionDir = path.join(\n logsDir,\n `vision-capture-${new Date().toISOString().replace(/[:.]/g, \"-\")}`\n );\n await fs.mkdir(sessionDir, { recursive: true });\n\n console.log(`✓ Created log directory: ${sessionDir}`);\n\n // Initialize capture data\n const captureData = {\n sessionId: `vision-capture-${Date.now()}`,\n startTime: new Date().toISOString(),\n endTime: \"\",\n runtime: {\n agentId: runtime.agentId,\n characterName: runtime.character.name,\n },\n camera: visionService.getCameraInfo(),\n captures: [] as VisionCaptureEntry[],\n statistics: {\n totalFrames: 0,\n totalSceneChanges: 0,\n totalObjectsDetected: 0,\n totalPeopleDetected: 0,\n averageChangePercentage: 0,\n objectTypeCounts: {} as Record<string, number>,\n poseCounts: {} as Record<string, number>,\n },\n };\n\n // Capture interval - every 500ms for 30 seconds = 60 captures\n const captureInterval = 500;\n const totalDuration = 30000;\n const expectedCaptures = totalDuration / captureInterval;\n\n console.log(\n `📸 Capturing vision data every ${captureInterval}ms for ${totalDuration / 1000} seconds...`\n );\n console.log(` Expected captures: ${expectedCaptures}`);\n\n let captureCount = 0;\n let totalChangePercentage = 0;\n let lastLoggedProgress = 0;\n\n const startTime = Date.now();\n\n while (Date.now() - startTime < totalDuration) {\n const captureStartTime = Date.now();\n\n try {\n // Get current scene description\n const scene = await visionService.getSceneDescription();\n const frame = await visionService.getCurrentFrame();\n\n // Capture image as base64\n const imageBuffer = await visionService.captureImage();\n let imageBase64: string | null = null;\n if (imageBuffer) {\n imageBase64 = imageBuffer.toString(\"base64\");\n }\n\n const capture = {\n index: captureCount,\n timestamp: new Date().toISOString(),\n timestampMs: Date.now(),\n elapsedMs: Date.now() - startTime,\n scene: scene\n ? {\n description: scene.description,\n changePercentage: scene.changePercentage,\n sceneChanged: scene.sceneChanged,\n objectCount: scene.objects.length,\n peopleCount: scene.people.length,\n objects: scene.objects,\n people: scene.people,\n }\n : null,\n frame: frame\n ? {\n width: frame.width,\n height: frame.height,\n format: frame.format,\n timestamp: frame.timestamp,\n }\n : null,\n imageBase64: imageBase64 ?? null,\n };\n\n captureData.captures.push(capture);\n\n // Save full image separately\n if (imageBase64) {\n const imagePath = path.join(\n sessionDir,\n `capture-${String(captureCount).padStart(3, \"0\")}.jpg`\n );\n await fs.writeFile(imagePath, Buffer.from(imageBase64, \"base64\"));\n }\n\n // Update statistics\n if (scene) {\n captureData.statistics.totalFrames++;\n if (scene.sceneChanged) {\n captureData.statistics.totalSceneChanges++;\n }\n if (scene.changePercentage) {\n totalChangePercentage += scene.changePercentage;\n }\n captureData.statistics.totalObjectsDetected += scene.objects.length;\n captureData.statistics.totalPeopleDetected += scene.people.length;\n\n // Count object types\n for (const obj of scene.objects) {\n captureData.statistics.objectTypeCounts[obj.type] =\n (captureData.statistics.objectTypeCounts[obj.type] || 0) + 1;\n }\n\n // Count poses\n for (const person of scene.people) {\n captureData.statistics.poseCounts[person.pose] =\n (captureData.statistics.poseCounts[person.pose] || 0) + 1;\n }\n\n // Save detailed scene log\n const sceneLogPath = path.join(\n sessionDir,\n `scene-${String(captureCount).padStart(3, \"0\")}.json`\n );\n await fs.writeFile(\n sceneLogPath,\n JSON.stringify(\n {\n capture: captureCount,\n timestamp: capture.timestamp,\n scene,\n frame: frame\n ? {\n width: frame.width,\n height: frame.height,\n format: frame.format,\n }\n : null,\n },\n null,\n 2\n )\n );\n }\n\n captureCount++;\n\n // Progress logging every 5 seconds\n const elapsedSeconds = Math.floor((Date.now() - startTime) / 1000);\n if (elapsedSeconds > lastLoggedProgress && elapsedSeconds % 5 === 0) {\n lastLoggedProgress = elapsedSeconds;\n const progress = (elapsedSeconds / 30) * 100;\n console.log(\n ` Progress: ${progress.toFixed(0)}% (${elapsedSeconds}/30s) - Captured ${captureCount} frames`\n );\n\n if (scene) {\n console.log(` Last scene: \"${scene.description.substring(0, 60)}...\"`);\n if (scene.objects.length > 0 || scene.people.length > 0) {\n console.log(\n ` Detected: ${scene.objects.length} objects, ${scene.people.length} people`\n );\n }\n }\n }\n } catch (error) {\n console.error(` Error in capture ${captureCount}:`, error);\n captureData.captures.push({\n index: captureCount,\n timestamp: new Date().toISOString(),\n error: error instanceof Error ? error.message : String(error),\n });\n captureCount++;\n }\n\n // Wait for next capture interval\n const captureEndTime = Date.now();\n const captureDuration = captureEndTime - captureStartTime;\n const waitTime = Math.max(0, captureInterval - captureDuration);\n\n if (waitTime > 0) {\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n }\n }\n\n // Finalize statistics\n captureData.endTime = new Date().toISOString();\n captureData.statistics.averageChangePercentage =\n captureData.statistics.totalFrames > 0\n ? totalChangePercentage / captureData.statistics.totalFrames\n : 0;\n\n // Save main capture log\n const mainLogPath = path.join(sessionDir, \"vision-capture-summary.json\");\n await fs.writeFile(mainLogPath, JSON.stringify(captureData, null, 2));\n\n // Generate markdown report\n const reportPath = path.join(sessionDir, \"vision-capture-report.md\");\n const report = `# Vision Capture Report\n\n## Session Information\n- **Session ID**: ${captureData.sessionId}\n- **Start Time**: ${captureData.startTime}\n- **End Time**: ${captureData.endTime}\n- **Duration**: 30 seconds\n- **Agent**: ${captureData.runtime.characterName} (${captureData.runtime.agentId})\n\n## Camera Information\n- **Name**: ${captureData.camera?.name || \"Unknown\"}\n- **ID**: ${captureData.camera?.id || \"Unknown\"}\n\n## Capture Statistics\n- **Total Frames Captured**: ${captureCount}\n- **Total Scene Changes**: ${captureData.statistics.totalSceneChanges}\n- **Average Change Percentage**: ${captureData.statistics.averageChangePercentage.toFixed(2)}%\n- **Total Objects Detected**: ${captureData.statistics.totalObjectsDetected}\n- **Total People Detected**: ${captureData.statistics.totalPeopleDetected}\n\n## Object Type Distribution\n${\n Object.entries(captureData.statistics.objectTypeCounts)\n .sort(([, a], [, b]) => b - a)\n .map(([type, count]) => `- **${type}**: ${count} detections`)\n .join(\"\\n\") || \"- No objects detected\"\n}\n\n## Pose Distribution\n${\n Object.entries(captureData.statistics.poseCounts)\n .map(([pose, count]) => `- **${pose}**: ${count} detections`)\n .join(\"\\n\") || \"- No people detected\"\n}\n\n## Sample Scene Descriptions\n${captureData.captures\n .filter((c) => c.scene?.description)\n .slice(0, 5)\n .map(\n (c, _i) => `### Capture ${c.index} (${c.elapsedMs ?? 0}ms)\n\"${c.scene?.description ?? \"\"}\"\n- Change: ${c.scene?.changePercentage?.toFixed(1) ?? \"0\"}%\n- Objects: ${c.scene?.objectCount ?? 0}\n- People: ${c.scene?.peopleCount ?? 0}`\n )\n .join(\"\\n\\n\")}\n\n## Files Generated\n- \\`vision-capture-summary.json\\` - Complete capture data\n- \\`vision-capture-report.md\\` - This report\n- \\`capture-XXX.jpg\\` - Individual captured images\n- \\`scene-XXX.json\\` - Detailed scene data for each capture\n`;\n\n await fs.writeFile(reportPath, report);\n\n console.log(\"\\n✅ Vision capture test completed!\");\n console.log(\"📊 Capture Summary:\");\n console.log(` - Total frames: ${captureCount}`);\n console.log(` - Scene changes: ${captureData.statistics.totalSceneChanges}`);\n console.log(\n ` - Average change: ${captureData.statistics.averageChangePercentage.toFixed(2)}%`\n );\n console.log(` - Objects detected: ${captureData.statistics.totalObjectsDetected}`);\n console.log(` - People detected: ${captureData.statistics.totalPeopleDetected}`);\n console.log(`\\n📁 Results saved to: ${sessionDir}`);\n console.log(\" - Summary: vision-capture-summary.json\");\n console.log(\" - Report: vision-capture-report.md\");\n console.log(\" - Images: capture-XXX.jpg\");\n console.log(\" - Scene data: scene-XXX.json\");\n\n console.log(\"✅ Vision capture log test PASSED\");\n },\n },\n ];\n}\n\nexport default new VisionCaptureLogTestSuite();\n",
23
- "import type { Action, Content, IAgentRuntime, Provider } from \"@elizaos/core\";\nimport { logger } from \"@elizaos/core\";\nimport type { VisionService } from \"../../service\";\nimport { VisionMode, VisionServiceType } from \"../../types\";\n\nexport class VisionRuntimeTestSuite {\n name = \"vision-runtime-tests\";\n description = \"Real runtime tests for vision plugin functionality\";\n\n tests = [\n {\n name: \"Vision service initialization\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing vision service initialization...\");\n\n const visionService = runtime.getService<VisionService>(VisionServiceType.VISION);\n if (!visionService) {\n throw new Error(\"Vision service not found in runtime\");\n }\n\n // Check if service is properly initialized\n if (typeof visionService.isActive !== \"function\") {\n throw new Error(\"Vision service missing isActive method\");\n }\n\n const isActive = visionService.isActive();\n logger.info(`[Test] Vision service active: ${isActive}`);\n\n // Service should be active after initialization\n if (!isActive && runtime.getSetting(\"VISION_MODE\") !== VisionMode.OFF) {\n throw new Error(\"Vision service should be active but is not\");\n }\n\n logger.info(\"[Test] ✅ Vision service initialization test passed\");\n },\n },\n\n {\n name: \"Scene description functionality\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing scene description...\");\n\n const visionService = runtime.getService<VisionService>(VisionServiceType.VISION);\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Get current scene description\n const scene = await visionService.getSceneDescription();\n\n if (!scene) {\n logger.warn(\"[Test] No scene description available (camera might not be connected)\");\n return; // Don't fail if no camera\n }\n\n // Validate scene structure\n if (typeof scene.timestamp !== \"number\") {\n throw new Error(\"Scene description missing timestamp\");\n }\n\n if (typeof scene.description !== \"string\") {\n throw new Error(\"Scene description missing description text\");\n }\n\n if (!Array.isArray(scene.objects)) {\n throw new Error(\"Scene description missing objects array\");\n }\n\n if (!Array.isArray(scene.people)) {\n throw new Error(\"Scene description missing people array\");\n }\n\n logger.info(`[Test] Scene: ${scene.description.substring(0, 100)}...`);\n logger.info(`[Test] Objects: ${scene.objects.length}, People: ${scene.people.length}`);\n logger.info(\"[Test] ✅ Scene description test passed\");\n },\n },\n\n {\n name: \"Vision mode switching\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing vision mode switching...\");\n\n const visionService = runtime.getService<VisionService>(VisionServiceType.VISION);\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Get current mode\n const originalMode = visionService.getVisionMode();\n logger.info(`[Test] Original mode: ${originalMode}`);\n\n // Test switching modes\n const testModes: VisionMode[] = [\n VisionMode.CAMERA,\n VisionMode.SCREEN,\n VisionMode.BOTH,\n VisionMode.OFF,\n ];\n\n for (const mode of testModes) {\n logger.info(`[Test] Switching to mode: ${mode}`);\n await visionService.setVisionMode(mode);\n\n const currentMode = visionService.getVisionMode();\n if (currentMode !== mode) {\n throw new Error(`Failed to switch to mode ${mode}, current mode is ${currentMode}`);\n }\n }\n\n // Restore original mode\n await visionService.setVisionMode(originalMode);\n logger.info(\"[Test] ✅ Vision mode switching test passed\");\n },\n },\n\n {\n name: \"DESCRIBE_SCENE action execution\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing DESCRIBE_SCENE action...\");\n\n // Find the action\n const action = (runtime.actions as Action[]).find((a) => a.name === \"DESCRIBE_SCENE\");\n if (!action) {\n throw new Error(\"DESCRIBE_SCENE action not found\");\n }\n\n // Create test message\n const message = {\n id: `test-msg-${Date.now()}`,\n entityId: \"test-entity\",\n roomId: \"test-room\",\n content: {\n text: \"Describe what you see\",\n source: \"test\",\n },\n createdAt: Date.now(),\n };\n\n // Validate action\n const isValid = await action.validate(runtime, message);\n if (!isValid) {\n throw new Error(\"DESCRIBE_SCENE action validation failed\");\n }\n\n // Execute action\n let responseReceived = false;\n const callback = async (response: Content) => {\n if (response.text && response.text.length > 0) {\n responseReceived = true;\n logger.info(`[Test] Action response: ${response.text.substring(0, 100)}...`);\n }\n return [];\n };\n\n await action.handler(runtime, message, { values: {}, data: {}, text: \"\" }, {}, callback);\n\n if (!responseReceived) {\n throw new Error(\"DESCRIBE_SCENE action did not produce a response\");\n }\n\n logger.info(\"[Test] ✅ DESCRIBE_SCENE action test passed\");\n },\n },\n\n {\n name: \"Vision provider integration\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing vision provider...\");\n\n // Find the vision provider\n const provider = (runtime.providers as Provider[]).find((p) => p.name === \"visionProvider\");\n if (!provider) {\n throw new Error(\"Vision provider not found\");\n }\n\n // Create test message and state\n const message = {\n id: `test-msg-${Date.now()}`,\n entityId: \"test-entity\",\n roomId: \"test-room\",\n content: { text: \"test\", source: \"test\" },\n createdAt: Date.now(),\n };\n\n const state = {\n values: {},\n data: {},\n text: \"\",\n };\n\n // Get provider data\n const result = await provider.get(runtime, message, state);\n\n if (!result || typeof result !== \"object\") {\n throw new Error(\"Vision provider returned invalid result\");\n }\n\n // Check if provider returns vision data when available\n if (result.text?.includes(\"I can see\")) {\n logger.info(`[Test] Provider text: ${result.text.substring(0, 100)}...`);\n }\n\n logger.info(\"[Test] ✅ Vision provider test passed\");\n },\n },\n\n {\n name: \"Florence-2 model initialization\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing Florence-2 model...\");\n\n const visionService = runtime.getService<VisionService>(VisionServiceType.VISION);\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Check if Florence-2 is enabled\n const florence2Enabled =\n runtime.getSetting(\"FLORENCE2_ENABLED\") === \"true\" ||\n runtime.getSetting(\"VISION_FLORENCE2_ENABLED\") === \"true\";\n\n if (!florence2Enabled) {\n logger.info(\"[Test] Florence-2 is disabled, skipping test\");\n return;\n }\n\n // If screen mode is enabled, Florence-2 should be initialized\n const mode = visionService.getVisionMode();\n if (mode === VisionMode.SCREEN || mode === VisionMode.BOTH) {\n // Try to get screen capture\n const screenCapture = await visionService.getScreenCapture();\n if (screenCapture) {\n logger.info(\"[Test] Screen capture available\");\n logger.info(`[Test] Screen size: ${screenCapture.width}x${screenCapture.height}`);\n logger.info(`[Test] Tiles: ${screenCapture.tiles.length}`);\n }\n }\n\n logger.info(\"[Test] ✅ Florence-2 model test passed\");\n },\n },\n\n {\n name: \"OCR service functionality\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing OCR service...\");\n\n const visionService = runtime.getService<VisionService>(VisionServiceType.VISION);\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Check if OCR is enabled\n const ocrEnabled =\n runtime.getSetting(\"OCR_ENABLED\") === \"true\" ||\n runtime.getSetting(\"VISION_OCR_ENABLED\") === \"true\";\n\n if (!ocrEnabled) {\n logger.info(\"[Test] OCR is disabled, skipping test\");\n return;\n }\n\n // If screen mode is enabled, OCR should work\n const mode = visionService.getVisionMode();\n if (mode === VisionMode.SCREEN || mode === VisionMode.BOTH) {\n const enhancedScene = await visionService.getEnhancedSceneDescription();\n if (enhancedScene?.screenAnalysis) {\n const ocrText = enhancedScene.screenAnalysis.fullScreenOCR;\n if (ocrText) {\n logger.info(`[Test] OCR extracted ${ocrText.length} characters`);\n logger.info(`[Test] OCR sample: ${ocrText.substring(0, 100)}...`);\n }\n }\n }\n\n logger.info(\"[Test] ✅ OCR service test passed\");\n },\n },\n\n {\n name: \"Entity tracking system\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing entity tracking...\");\n\n const visionService = runtime.getService<VisionService>(VisionServiceType.VISION);\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Get entity tracker\n const entityTracker = visionService.getEntityTracker();\n if (!entityTracker) {\n throw new Error(\"Entity tracker not found\");\n }\n\n // Get current entities\n const entities = entityTracker.getActiveEntities();\n logger.info(`[Test] Active entities: ${entities.length}`);\n\n // Check entity structure if any exist\n for (const entity of entities) {\n if (!entity.id || !entity.entityType || !entity.lastSeen) {\n throw new Error(\"Entity missing required fields\");\n }\n\n logger.info(\n `[Test] Entity ${entity.id}: type=${entity.entityType}, tracked=${entity.lastSeen - entity.firstSeen}ms`\n );\n }\n\n logger.info(\"[Test] ✅ Entity tracking test passed\");\n },\n },\n ];\n}\n\n// Export default instance for test runner\nexport default new VisionRuntimeTestSuite();\n",
24
- "import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { IAgentRuntime } from \"@elizaos/core\";\nimport type { VisionService } from \"../../service\";\nimport { VisionServiceType } from \"../../types\";\nimport {\n generateComplexPattern,\n generateQuadrantPattern,\n savePattern,\n verifyQuadrantNumbers,\n} from \"../test-pattern-generator\";\n\nconst execAsync = promisify(exec);\n\nexport class VisionWorkerE2ETestSuite {\n name = \"plugin-vision-workers-e2e\";\n description = \"E2E tests for multi-threaded vision system with worker threads\";\n\n tests = [\n {\n name: \"Should access vision service through runtime\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing vision service access through runtime...\");\n\n // Get vision service from runtime\n const visionService = runtime.getService<VisionService>(VisionServiceType.VISION);\n\n if (!visionService) {\n throw new Error(\"Vision service not found in runtime\");\n }\n\n console.log(\"✓ Vision service found in runtime\");\n\n // Check if service is active\n const isActive = visionService.isActive();\n console.log(`✓ Vision service active: ${isActive}`);\n\n // Get vision mode\n const mode = visionService.getVisionMode();\n console.log(`✓ Vision mode: ${mode}`);\n\n // Get enhanced scene description (which uses worker manager if available)\n const scene = await visionService.getEnhancedSceneDescription();\n if (scene) {\n console.log(\"✓ Enhanced scene available\");\n if (scene.screenAnalysis) {\n console.log(\" - Screen analysis present\");\n }\n }\n },\n },\n\n {\n name: \"Should capture screen at high FPS through service\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing high-FPS screen capture through service...\");\n\n const visionService = runtime.getService<VisionService>(VisionServiceType.VISION);\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Monitor for 5 seconds\n console.log(\"Monitoring screen capture for 5 seconds...\");\n const startTime = Date.now();\n let frameCount = 0;\n let lastTimestamp = 0;\n\n while (Date.now() - startTime < 5000) {\n const scene = await visionService.getEnhancedSceneDescription();\n if (scene && scene.timestamp !== lastTimestamp) {\n frameCount++;\n lastTimestamp = scene.timestamp;\n }\n\n // Non-blocking check\n await new Promise((resolve) => setImmediate(resolve));\n }\n\n const totalTime = (Date.now() - startTime) / 1000;\n const avgFPS = frameCount / totalTime;\n console.log(\n `✓ Captured ${frameCount} unique frames in ${totalTime.toFixed(2)}s (${avgFPS.toFixed(2)} FPS)`\n );\n\n if (avgFPS < 1) {\n console.warn(\"⚠️ FPS is lower than expected - workers may not be enabled\");\n }\n },\n },\n\n {\n name: \"Should detect quadrant numbers using OCR through service\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing quadrant number detection through service...\");\n\n const visionService = runtime.getService<VisionService>(VisionServiceType.VISION);\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Generate test pattern\n const pattern = await generateQuadrantPattern({\n width: 1920,\n height: 1080,\n fontSize: 72,\n includeGrid: true,\n });\n\n const patternPath = await savePattern(pattern, \"quadrant-test.png\");\n console.log(`✓ Test pattern saved to ${patternPath}`);\n\n // Display the pattern\n await displayTestPattern(patternPath);\n\n try {\n // Wait for OCR to process\n console.log(\"Waiting for OCR processing...\");\n await new Promise((resolve) => setTimeout(resolve, 3000));\n\n // Get enhanced scene with OCR results\n const scene = await visionService.getEnhancedSceneDescription();\n const ocrText = scene?.screenAnalysis?.fullScreenOCR || \"\";\n\n console.log(`OCR detected text: \"${ocrText.substring(0, 100)}...\"`);\n\n // Verify quadrant numbers\n const verification = verifyQuadrantNumbers(ocrText);\n console.log(`Found numbers: ${verification.foundNumbers.join(\", \")}`);\n\n if (verification.success) {\n console.log(\"✓ All quadrant numbers detected correctly\");\n } else {\n console.warn(`⚠️ Missing numbers: ${verification.missingNumbers.join(\", \")}`);\n }\n\n await closeTestPattern();\n } catch (error) {\n await closeTestPattern();\n throw error;\n }\n },\n },\n\n {\n name: \"Should handle multiple displays through service\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing multi-display support through service...\");\n\n const visionService = runtime.getService<VisionService>(VisionServiceType.VISION);\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Get display count\n const displayCount = await getDisplayCount();\n console.log(`Found ${displayCount} display(s)`);\n\n if (displayCount <= 1) {\n console.log(\"⚠️ Only one display found, skipping multi-display test\");\n return;\n }\n\n // Run for 10 seconds to cycle through displays\n console.log(\"Monitoring displays for 10 seconds...\");\n const startTime = Date.now();\n\n while (Date.now() - startTime < 10000) {\n const scene = await visionService.getEnhancedSceneDescription();\n if (scene?.screenCapture) {\n // Log current screen info\n console.log(` Screen: ${scene.screenCapture.width}x${scene.screenCapture.height}`);\n }\n\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n\n console.log(`✓ Monitored ${displayCount} displays`);\n },\n },\n\n {\n name: \"Should process Florence-2 and OCR in parallel through service\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing parallel processing performance through service...\");\n\n const visionService = runtime.getService<VisionService>(VisionServiceType.VISION);\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Generate complex pattern\n const pattern = await generateComplexPattern({\n width: 1920,\n height: 1080,\n });\n\n const patternPath = await savePattern(pattern, \"complex-test.png\");\n await displayTestPattern(patternPath);\n\n try {\n // Monitor performance for 10 seconds\n console.log(\"Running parallel processing test for 10 seconds...\");\n const startTime = Date.now();\n const stats = {\n frames: 0,\n ocrDetections: 0,\n florence2Detections: 0,\n };\n\n while (Date.now() - startTime < 10000) {\n const scene = await visionService.getEnhancedSceneDescription();\n\n if (scene) {\n stats.frames++;\n\n if (scene.screenAnalysis?.fullScreenOCR) {\n stats.ocrDetections++;\n }\n\n if (scene.screenAnalysis?.activeTile?.florence2) {\n stats.florence2Detections++;\n }\n }\n\n // Log every 2 seconds\n if ((Date.now() - startTime) % 2000 < 100) {\n console.log(\"\\nCurrent stats:\");\n console.log(` Frames: ${stats.frames}`);\n console.log(` OCR detections: ${stats.ocrDetections}`);\n console.log(` Florence-2 detections: ${stats.florence2Detections}`);\n }\n\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n const totalTime = (Date.now() - startTime) / 1000;\n console.log(\"\\nFinal statistics:\");\n console.log(` Total frames: ${stats.frames}`);\n console.log(` Average FPS: ${(stats.frames / totalTime).toFixed(2)}`);\n console.log(\n ` OCR success rate: ${((stats.ocrDetections / stats.frames) * 100).toFixed(1)}%`\n );\n console.log(\n ` Florence-2 success rate: ${((stats.florence2Detections / stats.frames) * 100).toFixed(1)}%`\n );\n\n await closeTestPattern();\n } catch (error) {\n await closeTestPattern();\n throw error;\n }\n },\n },\n ];\n}\n\n// Helper functions\n\nasync function getDisplayCount(): Promise<number> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n const { stdout } = await execAsync(\"system_profiler SPDisplaysDataType -json\");\n const data = JSON.parse(stdout);\n return data.SPDisplaysDataType?.[0]?._items?.length || 1;\n } else if (platform === \"linux\") {\n const { stdout } = await execAsync('xrandr --query | grep \" connected\" | wc -l');\n return parseInt(stdout.trim(), 10) || 1;\n } else if (platform === \"win32\") {\n const { stdout } = await execAsync(\n 'wmic path Win32_DesktopMonitor get DeviceID /format:csv | find /c \"DISPLAY\"'\n );\n return parseInt(stdout.trim(), 10) || 1;\n }\n } catch (error) {\n console.error(\"Failed to get display count:\", error);\n }\n\n return 1;\n}\n\nasync function displayTestPattern(imagePath: string): Promise<void> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // Open in Preview\n await execAsync(`open \"${imagePath}\"`);\n } else if (platform === \"linux\") {\n // Try common image viewers\n try {\n await execAsync(`xdg-open \"${imagePath}\"`);\n } catch {\n await execAsync(`display \"${imagePath}\"`);\n }\n } else if (platform === \"win32\") {\n // Open with default image viewer\n await execAsync(`start \"\" \"${imagePath}\"`);\n }\n\n // Give time for window to open\n await new Promise((resolve) => setTimeout(resolve, 1000));\n } catch (error) {\n console.warn(\"Could not display test pattern:\", error);\n }\n}\n\nasync function closeTestPattern(): Promise<void> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // Close Preview\n await execAsync(\"osascript -e 'tell application \\\"Preview\\\" to quit'\");\n } else if (platform === \"linux\") {\n // Close common viewers\n await execAsync('pkill -f \"display.*test-patterns\" || pkill -f \"eog.*test-patterns\" || true');\n } else if (platform === \"win32\") {\n // Close Photos app\n await execAsync(\"taskkill /IM Microsoft.Photos.exe /F 2>nul || exit 0\");\n }\n } catch (_error) {\n // Ignore errors when closing\n }\n}\n\nexport default new VisionWorkerE2ETestSuite();\n",
25
- "import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { logger } from \"@elizaos/core\";\nimport sharp from \"sharp\";\n\nexport interface TestPatternConfig {\n width: number;\n height: number;\n backgroundColor?: string;\n textColor?: string;\n fontSize?: number;\n includeGrid?: boolean;\n includeTimestamp?: boolean;\n displayIndex?: number;\n}\n\n/**\n * Generate grid lines for the pattern\n */\nfunction generateGrid(width: number, height: number, spacing: number = 100): string {\n const lines: string[] = [];\n\n // Vertical lines\n for (let x = spacing; x < width; x += spacing) {\n lines.push(\n `<line x1=\"${x}\" y1=\"0\" x2=\"${x}\" y2=\"${height}\" stroke=\"#eeeeee\" stroke-width=\"1\"/>`\n );\n }\n\n // Horizontal lines\n for (let y = spacing; y < height; y += spacing) {\n lines.push(\n `<line x1=\"0\" y1=\"${y}\" x2=\"${width}\" y2=\"${y}\" stroke=\"#eeeeee\" stroke-width=\"1\"/>`\n );\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Generate a test pattern with numbers in each quadrant and center\n */\nexport async function generateQuadrantPattern(config: TestPatternConfig): Promise<Buffer> {\n const {\n width,\n height,\n backgroundColor = \"#ffffff\",\n textColor = \"#000000\",\n fontSize = 48,\n includeGrid = true,\n includeTimestamp = true,\n displayIndex = 0,\n } = config;\n\n // Create SVG with test pattern\n const svg = `\n <svg width=\"${width}\" height=\"${height}\" xmlns=\"http://www.w3.org/2000/svg\">\n <!-- Background -->\n <rect width=\"${width}\" height=\"${height}\" fill=\"${backgroundColor}\"/>\n \n ${includeGrid ? generateGrid(width, height) : \"\"}\n \n <!-- Quadrant dividers -->\n <line x1=\"${width / 2}\" y1=\"0\" x2=\"${width / 2}\" y2=\"${height}\" stroke=\"#cccccc\" stroke-width=\"2\"/>\n <line x1=\"0\" y1=\"${height / 2}\" x2=\"${width}\" y2=\"${height / 2}\" stroke=\"#cccccc\" stroke-width=\"2\"/>\n \n <!-- Quadrant numbers -->\n <text x=\"${width / 4}\" y=\"${height / 4}\" font-family=\"Arial\" font-size=\"${fontSize}\" fill=\"${textColor}\" text-anchor=\"middle\" dominant-baseline=\"middle\">1</text>\n <text x=\"${(3 * width) / 4}\" y=\"${height / 4}\" font-family=\"Arial\" font-size=\"${fontSize}\" fill=\"${textColor}\" text-anchor=\"middle\" dominant-baseline=\"middle\">2</text>\n <text x=\"${width / 4}\" y=\"${(3 * height) / 4}\" font-family=\"Arial\" font-size=\"${fontSize}\" fill=\"${textColor}\" text-anchor=\"middle\" dominant-baseline=\"middle\">3</text>\n <text x=\"${(3 * width) / 4}\" y=\"${(3 * height) / 4}\" font-family=\"Arial\" font-size=\"${fontSize}\" fill=\"${textColor}\" text-anchor=\"middle\" dominant-baseline=\"middle\">4</text>\n \n <!-- Center number -->\n <circle cx=\"${width / 2}\" cy=\"${height / 2}\" r=\"${fontSize}\" fill=\"#ff0000\" opacity=\"0.3\"/>\n <text x=\"${width / 2}\" y=\"${height / 2}\" font-family=\"Arial\" font-size=\"${fontSize}\" fill=\"${textColor}\" text-anchor=\"middle\" dominant-baseline=\"middle\">5</text>\n \n <!-- Display info -->\n <text x=\"20\" y=\"30\" font-family=\"Arial\" font-size=\"16\" fill=\"${textColor}\">Display ${displayIndex}</text>\n <text x=\"20\" y=\"50\" font-family=\"Arial\" font-size=\"16\" fill=\"${textColor}\">${width}x${height}</text>\n \n ${includeTimestamp ? `<text x=\"20\" y=\"70\" font-family=\"Arial\" font-size=\"16\" fill=\"${textColor}\">Time: ${new Date().toISOString()}</text>` : \"\"}\n \n <!-- Corner markers -->\n <circle cx=\"10\" cy=\"10\" r=\"5\" fill=\"#ff0000\"/>\n <circle cx=\"${width - 10}\" cy=\"10\" r=\"5\" fill=\"#00ff00\"/>\n <circle cx=\"10\" cy=\"${height - 10}\" r=\"5\" fill=\"#0000ff\"/>\n <circle cx=\"${width - 10}\" cy=\"${height - 10}\" r=\"5\" fill=\"#ffff00\"/>\n </svg>\n `;\n\n // Convert SVG to PNG\n const buffer = await sharp(Buffer.from(svg)).png().toBuffer();\n\n return buffer;\n}\n\n/**\n * Generate a complex test pattern with multiple text regions\n */\nexport async function generateComplexPattern(config: TestPatternConfig): Promise<Buffer> {\n const {\n width,\n height,\n backgroundColor = \"#f0f0f0\",\n textColor = \"#000000\",\n fontSize = 24,\n displayIndex = 0,\n } = config;\n\n // Sample text for OCR testing\n const sampleTexts = [\n \"The quick brown fox jumps over the lazy dog\",\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\",\n \"abcdefghijklmnopqrstuvwxyz\",\n \"0123456789\",\n \"!@#$%^&*()_+-=[]{}|;:,.<>?\",\n ];\n\n const svg = `\n <svg width=\"${width}\" height=\"${height}\" xmlns=\"http://www.w3.org/2000/svg\">\n <!-- Background -->\n <rect width=\"${width}\" height=\"${height}\" fill=\"${backgroundColor}\"/>\n \n <!-- Title -->\n <text x=\"${width / 2}\" y=\"50\" font-family=\"Arial\" font-size=\"32\" fill=\"${textColor}\" text-anchor=\"middle\">Vision Test Pattern - Display ${displayIndex}</text>\n \n <!-- Text regions for OCR testing -->\n ${sampleTexts\n .map(\n (text, i) => `\n <rect x=\"50\" y=\"${150 + i * 80}\" width=\"${width - 100}\" height=\"60\" fill=\"white\" stroke=\"#333\" stroke-width=\"1\"/>\n <text x=\"70\" y=\"${185 + i * 80}\" font-family=\"Arial\" font-size=\"${fontSize}\" fill=\"${textColor}\">${text}</text>\n `\n )\n .join(\"\")}\n \n <!-- UI Elements -->\n <rect x=\"50\" y=\"${height - 200}\" width=\"150\" height=\"40\" fill=\"#007bff\" rx=\"5\"/>\n <text x=\"125\" y=\"${height - 175}\" font-family=\"Arial\" font-size=\"16\" fill=\"white\" text-anchor=\"middle\">Button</text>\n \n <rect x=\"220\" y=\"${height - 200}\" width=\"200\" height=\"30\" fill=\"white\" stroke=\"#333\" stroke-width=\"1\"/>\n <text x=\"230\" y=\"${height - 180}\" font-family=\"Arial\" font-size=\"14\" fill=\"#666\">Input Field</text>\n \n <!-- Timestamp -->\n <text x=\"${width - 20}\" y=\"${height - 20}\" font-family=\"Arial\" font-size=\"12\" fill=\"#666\" text-anchor=\"end\">${new Date().toISOString()}</text>\n </svg>\n `;\n\n const buffer = await sharp(Buffer.from(svg)).png().toBuffer();\n\n return buffer;\n}\n\n/**\n * Save test pattern to file\n */\nexport async function savePattern(buffer: Buffer, filename: string): Promise<string> {\n const outputDir = path.join(process.cwd(), \"test-patterns\");\n await fs.mkdir(outputDir, { recursive: true });\n\n const filepath = path.join(outputDir, filename);\n await fs.writeFile(filepath, buffer);\n\n logger.info(`[TestPatternGenerator] Saved test pattern to ${filepath}`);\n return filepath;\n}\n\n/**\n * Generate patterns for all displays\n */\nexport async function generatePatternsForAllDisplays(\n displayCount: number\n): Promise<Map<number, Buffer>> {\n const patterns = new Map<number, Buffer>();\n\n for (let i = 0; i < displayCount; i++) {\n const pattern = await generateQuadrantPattern({\n width: 1920,\n height: 1080,\n displayIndex: i,\n includeTimestamp: true,\n });\n\n patterns.set(i, pattern);\n }\n\n return patterns;\n}\n\n/**\n * Verify OCR results match expected quadrant numbers\n */\nexport function verifyQuadrantNumbers(ocrText: string): {\n success: boolean;\n foundNumbers: number[];\n missingNumbers: number[];\n} {\n const expectedNumbers = [1, 2, 3, 4, 5];\n const foundNumbers: number[] = [];\n\n // Extract all numbers from OCR text\n const matches = ocrText.match(/\\d+/g);\n if (matches) {\n matches.forEach((match) => {\n const num = parseInt(match, 10);\n if (expectedNumbers.includes(num) && !foundNumbers.includes(num)) {\n foundNumbers.push(num);\n }\n });\n }\n\n const missingNumbers = expectedNumbers.filter((n) => !foundNumbers.includes(n));\n\n return {\n success: missingNumbers.length === 0,\n foundNumbers,\n missingNumbers,\n };\n}\n",
26
- "// Export all E2E test suites\n\nexport { default as ScreenVisionE2ETestSuite } from \"./screen-vision\";\nexport { default as VisionBasicE2ETestSuite } from \"./vision-basic\";\nexport { default as VisionCaptureLogTestSuite } from \"./vision-capture-log\";\nexport { default as VisionRuntimeTestSuite } from \"./vision-runtime\";\nexport { default as VisionWorkerE2ETestSuite } from \"./vision-worker-tests\";\n\nimport ScreenVisionE2ETestSuite from \"./screen-vision\";\n// Export as array for convenience\nimport VisionBasicE2ETestSuite from \"./vision-basic\";\nimport VisionCaptureLogTestSuite from \"./vision-capture-log\";\nimport VisionRuntimeTestSuite from \"./vision-runtime\";\nimport VisionWorkerE2ETestSuite from \"./vision-worker-tests\";\n\nexport const testSuites = [\n VisionRuntimeTestSuite, // Real runtime tests first\n VisionBasicE2ETestSuite,\n VisionCaptureLogTestSuite,\n ScreenVisionE2ETestSuite,\n VisionWorkerE2ETestSuite, // Worker-based tests\n];\n\nexport default testSuites;\n",
27
- "import type { Plugin, TestSuite } from \"@elizaos/core\";\nimport {\n captureImageAction,\n describeSceneAction,\n identifyPersonAction,\n nameEntityAction,\n setVisionModeAction,\n trackEntityAction,\n} from \"./action\";\nimport { visionProvider } from \"./provider\";\nimport { VisionService } from \"./service\";\nimport { testSuites } from \"./tests/e2e/index\";\n\nexport const visionPlugin: Plugin = {\n name: \"vision\",\n description: \"Provides visual perception through camera integration and scene analysis\",\n services: [VisionService],\n providers: [visionProvider],\n actions: [\n describeSceneAction,\n captureImageAction,\n setVisionModeAction,\n nameEntityAction,\n identifyPersonAction,\n trackEntityAction,\n ],\n tests: testSuites as unknown as TestSuite[],\n init: async (_config, _runtime) => {},\n};\n\nexport default visionPlugin;\n"
5
+ "import type { Plugin, TestSuite } from \"@elizaos/core\";\nimport { promoteSubactionsToActions } from \"@elizaos/core\";\nimport { visionAction } from \"./action\";\nimport { visionProvider } from \"./provider\";\nimport { VisionService } from \"./service\";\nimport { testSuites } from \"./tests/e2e/index\";\n\nexport const visionPlugin: Plugin = {\n name: \"vision\",\n description:\n \"Provides visual perception through camera integration and scene analysis\",\n services: [VisionService],\n providers: [visionProvider],\n actions: [...promoteSubactionsToActions(visionAction)],\n tests: testSuites as TestSuite[],\n // Self-declared auto-enable: activate when features.vision is enabled OR\n // when media.vision.provider is configured.\n autoEnable: {\n shouldEnable: (_env, config) => {\n const f = (config?.features as Record<string, unknown> | undefined)\n ?.vision;\n const featureOn =\n f === true ||\n (typeof f === \"object\" &&\n f !== null &&\n (f as { enabled?: unknown }).enabled !== false);\n if (featureOn) return true;\n const media = config?.media as Record<string, unknown> | undefined;\n const visionMedia = media?.vision as\n | { enabled?: unknown; provider?: unknown }\n | undefined;\n return Boolean(\n visionMedia &&\n visionMedia.enabled !== false &&\n typeof visionMedia.provider === \"string\" &&\n visionMedia.provider.length > 0,\n );\n },\n },\n init: async (_config, _runtime) => {},\n};\n\nexport default visionPlugin;\n",
6
+ "import {\n type Action,\n type ActionExample,\n type ActionResult,\n ContentType,\n createUniqueUuid,\n type HandlerCallback,\n type IAgentRuntime,\n logger,\n type Media,\n type Memory,\n type State,\n} from \"@elizaos/core\";\nimport type { VisionService } from \"./service\";\nimport { VisionMode } from \"./types\";\n\nconst VISION_ACTION_TIMEOUT_MS = 10_000;\nconst MAX_VISION_TEXT_LENGTH = 4000;\nconst MAX_VISION_ENTITIES = 25;\n\nconst VISION_OPS = [\n \"describe\",\n \"capture\",\n \"set_mode\",\n \"name_entity\",\n \"identify_person\",\n \"track_entity\",\n] as const;\n\ntype VisionOp = (typeof VISION_OPS)[number];\n\nconst ALL_VISION_CONTEXTS = [\n \"media\",\n \"screen_time\",\n \"automation\",\n \"memory\",\n \"settings\",\n] as const;\n\nconst DESCRIBE_KEYWORDS = [\n \"describe\",\n \"scene\",\n \"see\",\n \"look\",\n \"camera\",\n \"screen\",\n \"object\",\n \"person\",\n \"escena\",\n \"ver\",\n \"camara\",\n \"décrire\",\n \"scène\",\n \"voir\",\n \"beschreiben\",\n \"szene\",\n \"sehen\",\n \"descrivi\",\n \"scena\",\n \"vedi\",\n \"説明\",\n \"見える\",\n \"场景\",\n \"描述\",\n \"看见\",\n \"장면\",\n \"설명\",\n \"보여\",\n];\n\nconst CAPTURE_KEYWORDS = [\n \"capture\",\n \"image\",\n \"photo\",\n \"picture\",\n \"snapshot\",\n \"screenshot\",\n \"camera\",\n \"captura\",\n \"foto\",\n \"imagen\",\n \"capturer\",\n \"photo\",\n \"bild\",\n \"foto\",\n \"capturare\",\n \"写真\",\n \"画像\",\n \"スクリーンショット\",\n \"拍照\",\n \"截图\",\n \"이미지\",\n \"사진\",\n \"스크린샷\",\n];\n\nconst SET_MODE_KEYWORDS = [\n \"vision\",\n \"mode\",\n \"camera\",\n \"screen\",\n \"both\",\n \"disable\",\n \"enable\",\n \"off\",\n \"visión\",\n \"camara\",\n \"pantalla\",\n \"écran\",\n \"kamera\",\n \"bildschirm\",\n \"schermo\",\n \"ビジョン\",\n \"カメラ\",\n \"画面\",\n \"视觉\",\n \"相机\",\n \"屏幕\",\n \"비전\",\n \"카메라\",\n \"화면\",\n];\n\nconst NAME_ENTITY_KEYWORDS = [\n \"name\",\n \"named\",\n \"call\",\n \"person\",\n \"entity\",\n \"remember\",\n \"object\",\n \"nombre\",\n \"llama\",\n \"persona\",\n \"nom\",\n \"appelle\",\n \"personne\",\n \"name\",\n \"nenne\",\n \"person\",\n \"nome\",\n \"chiama\",\n \"persona\",\n \"名前\",\n \"呼ぶ\",\n \"人\",\n \"命名\",\n \"叫\",\n \"人\",\n \"이름\",\n \"불러\",\n \"사람\",\n];\n\nconst IDENTIFY_PERSON_KEYWORDS = [\n \"identify\",\n \"recognize\",\n \"who is\",\n \"person\",\n \"face\",\n \"seen before\",\n \"identificar\",\n \"reconoces\",\n \"persona\",\n \"visage\",\n \"reconnais\",\n \"personne\",\n \"erkennen\",\n \"gesicht\",\n \"person\",\n \"riconosci\",\n \"persona\",\n \"識別\",\n \"誰\",\n \"顔\",\n \"识别\",\n \"是谁\",\n \"人\",\n \"식별\",\n \"누구\",\n \"얼굴\",\n];\n\nconst TRACK_ENTITY_KEYWORDS = [\n \"track\",\n \"follow\",\n \"watch\",\n \"keep an eye\",\n \"entity\",\n \"person\",\n \"object\",\n \"rastrear\",\n \"seguir\",\n \"vigilar\",\n \"persona\",\n \"suivre\",\n \"surveiller\",\n \"personne\",\n \"verfolgen\",\n \"beobachten\",\n \"person\",\n \"traccia\",\n \"segui\",\n \"persona\",\n \"追跡\",\n \"見張\",\n \"人\",\n \"跟踪\",\n \"关注\",\n \"人\",\n \"추적\",\n \"지켜봐\",\n \"사람\",\n];\n\nfunction withVisionTimeout<T>(promise: Promise<T>, label: string): Promise<T> {\n return Promise.race([\n promise,\n new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(`${label} timed out`)),\n VISION_ACTION_TIMEOUT_MS,\n ),\n ),\n ]);\n}\n\nasync function saveExecutionRecord(\n runtime: IAgentRuntime,\n messageContext: Memory,\n thought: string,\n text: string,\n actions?: string[],\n attachments?: Media[],\n): Promise<void> {\n const memory: Memory = {\n id: createUniqueUuid(runtime, `vision-record-${Date.now()}`),\n content: {\n text,\n thought,\n actions: actions || [\"VISION_ANALYSIS\"],\n attachments,\n },\n entityId: createUniqueUuid(runtime, runtime.agentId),\n agentId: runtime.agentId,\n roomId: messageContext.roomId,\n worldId: messageContext.worldId,\n createdAt: Date.now(),\n };\n await runtime.createMemory(memory, \"messages\");\n}\n\nfunction readActionParams(\n options?: Record<string, unknown>,\n): Record<string, unknown> {\n const direct =\n options && typeof options === \"object\"\n ? (options as Record<string, unknown>)\n : {};\n const parameters =\n direct.parameters && typeof direct.parameters === \"object\"\n ? (direct.parameters as Record<string, unknown>)\n : {};\n return { ...direct, ...parameters };\n}\n\nfunction selectedContextMatches(\n state: State | undefined,\n contexts: readonly string[],\n): boolean {\n const selected = new Set<string>();\n const collect = (value: unknown) => {\n if (!Array.isArray(value)) return;\n for (const item of value) {\n if (typeof item === \"string\") selected.add(item);\n }\n };\n collect(\n (state?.values as Record<string, unknown> | undefined)?.selectedContexts,\n );\n collect(\n (state?.data as Record<string, unknown> | undefined)?.selectedContexts,\n );\n const contextObject = (state?.data as Record<string, unknown> | undefined)\n ?.contextObject as\n | {\n trajectoryPrefix?: { selectedContexts?: unknown };\n metadata?: { selectedContexts?: unknown };\n }\n | undefined;\n collect(contextObject?.trajectoryPrefix?.selectedContexts);\n collect(contextObject?.metadata?.selectedContexts);\n return contexts.some((context) => selected.has(context));\n}\n\nfunction visionServiceIsActive(runtime: IAgentRuntime): boolean {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n return Boolean(visionService?.isActive());\n}\n\nfunction normalizeOp(value: unknown): VisionOp | null {\n if (typeof value !== \"string\") return null;\n const normalized = value\n .trim()\n .toLowerCase()\n .replace(/[\\s-]+/g, \"_\");\n if (!normalized) return null;\n const aliases: Record<string, VisionOp> = {\n describe_scene: \"describe\",\n scene: \"describe\",\n capture_image: \"capture\",\n image: \"capture\",\n photo: \"capture\",\n snapshot: \"capture\",\n screenshot: \"capture\",\n set_vision_mode: \"set_mode\",\n mode: \"set_mode\",\n vision_mode: \"set_mode\",\n name: \"name_entity\",\n identify: \"identify_person\",\n recognize: \"identify_person\",\n track: \"track_entity\",\n follow: \"track_entity\",\n };\n if (aliases[normalized]) return aliases[normalized];\n return (VISION_OPS as readonly string[]).includes(normalized)\n ? (normalized as VisionOp)\n : null;\n}\n\nfunction inferOpFromMessage(text: string): VisionOp | null {\n const lower = text.toLowerCase();\n if (\n NAME_ENTITY_KEYWORDS.some((k) => lower.includes(k.toLowerCase())) &&\n /\\b(call|name|named)\\b/.test(lower)\n ) {\n return \"name_entity\";\n }\n if (\n IDENTIFY_PERSON_KEYWORDS.some((k) => lower.includes(k.toLowerCase())) &&\n /\\b(who|identify|recognize)\\b/.test(lower)\n ) {\n return \"identify_person\";\n }\n if (\n TRACK_ENTITY_KEYWORDS.some((k) => lower.includes(k.toLowerCase())) &&\n /\\b(track|follow|watch|keep an eye)\\b/.test(lower)\n ) {\n return \"track_entity\";\n }\n if (\n SET_MODE_KEYWORDS.some((k) => lower.includes(k.toLowerCase())) &&\n /\\b(mode|enable|disable|turn off|turn on)\\b/.test(lower)\n ) {\n return \"set_mode\";\n }\n if (CAPTURE_KEYWORDS.some((k) => lower.includes(k.toLowerCase()))) {\n return \"capture\";\n }\n if (DESCRIBE_KEYWORDS.some((k) => lower.includes(k.toLowerCase()))) {\n return \"describe\";\n }\n return null;\n}\n\nasync function runDescribe(\n runtime: IAgentRuntime,\n message: Memory,\n options: Record<string, unknown>,\n callback?: HandlerCallback,\n): Promise<ActionResult> {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService || !visionService.isActive()) {\n const thought =\n \"Vision service is not available or no camera is connected.\";\n const text = \"I cannot see anything right now. No camera is available.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text: \"Vision service unavailable - cannot analyze scene\",\n values: {\n success: false,\n visionAvailable: false,\n error: \"Vision service not available\",\n },\n data: {\n actionName: \"VISION\",\n op: \"describe\",\n error: \"Vision service not available or no camera connected\",\n },\n };\n }\n\n try {\n const scene = await withVisionTimeout(\n visionService.getSceneDescription(),\n \"vision scene description\",\n );\n const cameraInfo = visionService.getCameraInfo();\n\n if (!scene) {\n const thought = \"Camera is connected but no scene has been analyzed yet.\";\n const text = `Camera \"${cameraInfo?.name}\" is connected, but I haven't analyzed any scenes yet. Please wait a moment.`;\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text: \"Camera connected but no scene analyzed yet\",\n values: {\n success: false,\n visionAvailable: true,\n sceneAnalyzed: false,\n cameraName: cameraInfo?.name || undefined,\n },\n data: {\n actionName: \"VISION\",\n op: \"describe\",\n cameraInfo: cameraInfo\n ? {\n id: cameraInfo.id,\n name: cameraInfo.name,\n connected: cameraInfo.connected,\n }\n : undefined,\n sceneStatus: \"not_analyzed\",\n },\n };\n }\n\n const peopleCount = scene.people.length;\n const objectCount = scene.objects.length;\n const people = scene.people.slice(0, MAX_VISION_ENTITIES);\n const objects = scene.objects.slice(0, MAX_VISION_ENTITIES);\n const timestamp = new Date(scene.timestamp).toLocaleString();\n const detailLevel =\n options.detailLevel === \"summary\" ? \"summary\" : \"detailed\";\n\n let description = `Looking through ${cameraInfo?.name || \"the camera\"}, `;\n description += scene.description;\n\n if (detailLevel === \"detailed\" && peopleCount > 0) {\n description += `\\n\\nI can see ${peopleCount} ${peopleCount === 1 ? \"person\" : \"people\"}`;\n const facingData = people.reduce(\n (acc, person) => {\n if (person.facing && person.facing !== \"unknown\") {\n acc[person.facing] = (acc[person.facing] || 0) + 1;\n }\n return acc;\n },\n {} as Record<string, number>,\n );\n\n if (Object.keys(facingData).length > 0) {\n const facingDescriptions = Object.entries(facingData).map(\n ([direction, count]) => `${count} facing ${direction}`,\n );\n description += ` (${facingDescriptions.join(\", \")})`;\n }\n description += \".\";\n }\n\n if (detailLevel === \"detailed\" && objectCount > 0) {\n const objectTypes = objects.reduce(\n (acc, obj) => {\n acc[obj.type] = (acc[obj.type] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>,\n );\n\n const objectDescriptions = Object.entries(objectTypes).map(\n ([type, count]) => `${count} ${type}${count > 1 ? \"s\" : \"\"}`,\n );\n description += `\\n\\nObjects detected: ${objectDescriptions.join(\", \")}.`;\n }\n\n if (\n detailLevel === \"detailed\" &&\n scene.sceneChanged &&\n scene.changePercentage\n ) {\n description += `\\n\\n(Scene changed by ${scene.changePercentage.toFixed(1)}% since last analysis)`;\n }\n\n const thought = `Analyzed the visual scene at ${timestamp}.`;\n const text = description.slice(0, MAX_VISION_TEXT_LENGTH);\n\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n\n return {\n success: true,\n text,\n values: {\n success: true,\n visionAvailable: true,\n sceneAnalyzed: true,\n peopleCount,\n objectCount,\n cameraName: cameraInfo?.name || undefined,\n sceneChanged: scene.sceneChanged,\n changePercentage: scene.changePercentage,\n detailLevel,\n },\n data: {\n actionName: \"VISION\",\n op: \"describe\",\n sceneTimestamp: scene.timestamp,\n sceneDescription: scene.description.slice(0, MAX_VISION_TEXT_LENGTH),\n sceneChanged: scene.sceneChanged,\n changePercentage: scene.changePercentage,\n audioTranscription: scene.audioTranscription || undefined,\n objectCount: objects.length,\n peopleCount: people.length,\n cameraInfo: cameraInfo\n ? {\n id: cameraInfo.id,\n name: cameraInfo.name,\n connected: cameraInfo.connected,\n }\n : undefined,\n timestamp,\n description: text,\n },\n };\n } catch (error: unknown) {\n logger.error(\n \"[VISION/describe] Error analyzing scene:\",\n error instanceof Error ? error.message : String(error),\n );\n const thought =\n \"An error occurred while trying to analyze the visual scene.\";\n const text = `Error analyzing scene: ${error instanceof Error ? error.message : String(error)}`;\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n text: \"Error analyzing scene\",\n values: {\n success: false,\n visionAvailable: true,\n error: true,\n errorMessage,\n },\n data: {\n actionName: \"VISION\",\n op: \"describe\",\n error: errorMessage,\n errorType: \"analysis_error\",\n },\n };\n }\n}\n\nasync function runCapture(\n runtime: IAgentRuntime,\n message: Memory,\n callback?: HandlerCallback,\n): Promise<ActionResult> {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService || !visionService.isActive()) {\n const thought =\n \"Vision service is not available or no camera is connected.\";\n const text = \"I cannot capture an image right now. No camera is available.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text: \"Vision service unavailable - cannot capture image\",\n values: {\n success: false,\n visionAvailable: false,\n error: \"Vision service not available\",\n },\n data: {\n actionName: \"VISION\",\n op: \"capture\",\n error: \"Vision service not available or no camera connected\",\n },\n };\n }\n\n try {\n const imageBuffer = await Promise.race([\n visionService.captureImage(),\n new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(\"vision capture timed out\")),\n VISION_ACTION_TIMEOUT_MS,\n ),\n ),\n ]);\n const cameraInfo = visionService.getCameraInfo();\n\n if (!imageBuffer) {\n const thought = \"Failed to capture image from camera.\";\n const text =\n \"I could not capture an image from the camera. Please try again.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text: \"Failed to capture image from camera\",\n values: {\n success: false,\n visionAvailable: true,\n captureSuccess: false,\n },\n data: {\n actionName: \"VISION\",\n op: \"capture\",\n error: \"Camera capture failed\",\n cameraInfo: cameraInfo\n ? {\n id: cameraInfo.id,\n name: cameraInfo.name,\n connected: cameraInfo.connected,\n }\n : undefined,\n },\n };\n }\n\n const attachmentId = createUniqueUuid(runtime, `capture-${Date.now()}`);\n const timestamp = new Date().toISOString();\n\n const imageAttachment: Media = {\n id: attachmentId,\n title: `Camera Capture - ${timestamp}`,\n contentType: ContentType.IMAGE,\n source: `camera:${cameraInfo?.name || \"unknown\"}`,\n url: `data:image/jpeg;base64,${imageBuffer.toString(\"base64\")}`,\n };\n\n const thought = `Captured an image from camera \"${cameraInfo?.name}\".`;\n const text = `I've captured an image from the camera at ${timestamp}.`;\n\n await saveExecutionRecord(\n runtime,\n message,\n thought,\n text,\n [\"VISION\"],\n [imageAttachment],\n );\n\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"VISION\"],\n attachments: [imageAttachment],\n });\n }\n\n return {\n success: true,\n text: `I've captured an image from the camera at ${timestamp}.`,\n values: {\n success: true,\n visionAvailable: true,\n captureSuccess: true,\n cameraName: cameraInfo?.name || undefined,\n timestamp,\n },\n data: {\n actionName: \"VISION\",\n op: \"capture\",\n imageAttachment: {\n id: imageAttachment.id,\n title: imageAttachment.title,\n contentType: imageAttachment.contentType,\n source: imageAttachment.source,\n url: imageAttachment.url,\n },\n cameraInfo: cameraInfo\n ? {\n id: cameraInfo.id,\n name: cameraInfo.name,\n connected: cameraInfo.connected,\n }\n : undefined,\n timestamp,\n },\n };\n } catch (error) {\n logger.error(\"[VISION/capture] Error capturing image:\", error);\n const thought = \"An error occurred while trying to capture an image.\";\n const errorMessage = error instanceof Error ? error.message : String(error);\n const text = `Error capturing image: ${errorMessage}`;\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n\n return {\n success: false,\n text: \"Error capturing image\",\n values: {\n success: false,\n visionAvailable: true,\n error: true,\n errorMessage,\n },\n data: {\n actionName: \"VISION\",\n op: \"capture\",\n error: errorMessage,\n errorType: \"capture_error\",\n },\n };\n }\n}\n\nasync function runSetMode(\n runtime: IAgentRuntime,\n message: Memory,\n options: Record<string, unknown>,\n callback?: HandlerCallback,\n): Promise<ActionResult> {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService) {\n const thought = \"Vision service is not available.\";\n const text =\n \"I cannot change vision mode because the vision service is not available.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n data: { actionName: \"VISION\", op: \"set_mode\" },\n };\n }\n\n try {\n const explicitMode =\n typeof options.mode === \"string\" ? options.mode.toLowerCase() : \"\";\n const messageText =\n explicitMode || message.content.text?.toLowerCase() || \"\";\n let newMode: VisionMode | null = null;\n\n if (messageText.includes(\"off\") || messageText.includes(\"disable\")) {\n newMode = VisionMode.OFF;\n } else if (messageText.includes(\"both\")) {\n newMode = VisionMode.BOTH;\n } else if (messageText.includes(\"screen\")) {\n newMode = VisionMode.SCREEN;\n } else if (messageText.includes(\"camera\")) {\n newMode = VisionMode.CAMERA;\n }\n\n if (!newMode) {\n const thought =\n \"Could not determine the desired vision mode from the message.\";\n const text =\n \"Please specify the vision mode: OFF, CAMERA, SCREEN, or BOTH.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n data: { actionName: \"VISION\", op: \"set_mode\" },\n };\n }\n\n const currentMode = visionService.getVisionMode();\n await Promise.race([\n visionService.setVisionMode(newMode),\n new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(\"vision mode change timed out\")),\n VISION_ACTION_TIMEOUT_MS,\n ),\n ),\n ]);\n\n const thought = `Changed vision mode from ${currentMode} to ${newMode}.`;\n let text = \"\";\n\n switch (newMode) {\n case VisionMode.OFF:\n text =\n \"Vision has been disabled. I will no longer process visual input.\";\n break;\n case VisionMode.CAMERA:\n text =\n \"Vision mode set to CAMERA only. I will process input from the camera.\";\n break;\n case VisionMode.SCREEN:\n text =\n \"Vision mode set to SCREEN only. I will analyze what's on your screen.\";\n break;\n case VisionMode.BOTH:\n text =\n \"Vision mode set to BOTH. I will process input from both camera and screen.\";\n break;\n }\n\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: true,\n text,\n values: { visionMode: newMode },\n data: { actionName: \"VISION\", op: \"set_mode\", visionMode: newMode },\n };\n } catch (error) {\n logger.error(\"[VISION/set_mode] Error changing vision mode:\", error);\n const errorMessage = error instanceof Error ? error.message : String(error);\n const thought = \"An error occurred while trying to change the vision mode.\";\n const text = `Error changing vision mode: ${errorMessage}`;\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n error: errorMessage,\n data: { actionName: \"VISION\", op: \"set_mode\" },\n };\n }\n}\n\nasync function runNameEntity(\n runtime: IAgentRuntime,\n message: Memory,\n options: Record<string, unknown>,\n callback?: HandlerCallback,\n): Promise<ActionResult> {\n try {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService) {\n const thought = \"Vision service is not available.\";\n const text =\n \"I cannot name entities because the vision service is not available.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n data: { actionName: \"VISION\", op: \"name_entity\" },\n };\n }\n\n const scene = await withVisionTimeout(\n visionService.getSceneDescription(),\n \"vision scene description\",\n );\n\n if (!scene || scene.people.length === 0) {\n const thought = \"No people visible to name.\";\n const text = \"I don't see any people in the current scene to name.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n data: { actionName: \"VISION\", op: \"name_entity\" },\n };\n }\n\n const messageText = message.content.text?.toLowerCase() || \"\";\n const explicitName =\n typeof options.name === \"string\" ? options.name.trim() : \"\";\n const nameMatch = explicitName\n ? [explicitName, explicitName]\n : messageText.match(/(?:named?|call(?:ed)?|is)\\s+(\\w+)/i);\n\n if (!nameMatch) {\n const thought = \"Could not extract name from message.\";\n const text =\n 'I couldn\\'t understand what name to assign. Please say something like \"The person is named Alice\".';\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n data: { actionName: \"VISION\", op: \"name_entity\" },\n };\n }\n\n const name = nameMatch[1];\n const entityTracker = visionService.getEntityTracker();\n\n await entityTracker.updateEntities(\n scene.objects.slice(0, MAX_VISION_ENTITIES),\n scene.people.slice(0, MAX_VISION_ENTITIES),\n undefined,\n runtime,\n );\n const activeEntities = entityTracker.getActiveEntities();\n const people = activeEntities.filter((e) => e.entityType === \"person\");\n\n if (people.length === 0) {\n const thought = \"No tracked people found.\";\n const text =\n \"I can see someone but haven't established tracking yet. Please try again in a moment.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n data: { actionName: \"VISION\", op: \"name_entity\" },\n };\n }\n\n let targetPerson = people[0];\n if (people.length > 1) {\n targetPerson = people.reduce((prev, curr) => {\n const prevArea = prev.lastPosition.width * prev.lastPosition.height;\n const currArea = curr.lastPosition.width * curr.lastPosition.height;\n return currArea > prevArea ? curr : prev;\n });\n }\n\n const success = entityTracker.assignNameToEntity(targetPerson.id, name);\n\n if (success) {\n const thought = `Named entity \"${name}\" and associated with person in scene.`;\n const text = `I've identified the person as ${name}. I'll remember them for future interactions.`;\n\n await saveExecutionRecord(\n runtime,\n message,\n thought,\n text,\n [\"VISION\"],\n undefined,\n );\n\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"VISION\"],\n data: { entityId: targetPerson.id, name },\n });\n }\n\n logger.info(\n `[VISION/name_entity] Assigned name \"${name}\" to entity ${targetPerson.id}`,\n );\n return {\n success: true,\n text,\n values: { entityId: targetPerson.id, name },\n data: {\n actionName: \"VISION\",\n op: \"name_entity\",\n entityId: targetPerson.id,\n name,\n },\n };\n } else {\n const thought = \"Failed to assign name to entity.\";\n const text = \"There was an error assigning the name. Please try again.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n data: { actionName: \"VISION\", op: \"name_entity\" },\n };\n }\n } catch (error) {\n logger.error(\"[VISION/name_entity] Error:\", error);\n const thought = \"Failed to name entity.\";\n const text = `Sorry, I couldn't name the entity: ${error instanceof Error ? error.message : \"Unknown error\"}`;\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n error: error instanceof Error ? error.message : String(error),\n data: { actionName: \"VISION\", op: \"name_entity\" },\n };\n }\n}\n\nasync function runIdentifyPerson(\n runtime: IAgentRuntime,\n message: Memory,\n callback?: HandlerCallback,\n): Promise<ActionResult> {\n try {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService) {\n const thought = \"Vision service is not available.\";\n const text =\n \"I cannot identify people because the vision service is not available.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n data: { actionName: \"VISION\", op: \"identify_person\" },\n };\n }\n\n const scene = await withVisionTimeout(\n visionService.getSceneDescription(),\n \"vision scene description\",\n );\n\n if (!scene || scene.people.length === 0) {\n const thought = \"No people visible to identify.\";\n const text = \"I don't see any people in the current scene.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n data: { actionName: \"VISION\", op: \"identify_person\" },\n };\n }\n\n const entityTracker = visionService.getEntityTracker();\n\n await entityTracker.updateEntities(\n scene.objects.slice(0, MAX_VISION_ENTITIES),\n scene.people.slice(0, MAX_VISION_ENTITIES),\n undefined,\n runtime,\n );\n const activeEntities = entityTracker.getActiveEntities();\n const people = activeEntities.filter((e) => e.entityType === \"person\");\n\n if (people.length === 0) {\n const thought = \"No tracked people found.\";\n const text = \"I can see someone but I'm still processing their identity.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n data: { actionName: \"VISION\", op: \"identify_person\" },\n };\n }\n\n let recognizedCount = 0;\n let unknownCount = 0;\n const identifications: string[] = [];\n\n for (const person of people) {\n const name = person.attributes.name;\n const duration = Date.now() - person.firstSeen;\n const durationStr =\n duration < 60000\n ? `${Math.round(duration / 1000)} seconds`\n : `${Math.round(duration / 60000)} minutes`;\n\n if (name) {\n recognizedCount++;\n const personInfo = `I can see ${name}. They've been here for ${durationStr}.`;\n identifications.push(personInfo);\n\n if (person.appearances.length > 5) {\n identifications.push(\"I've been tracking them consistently.\");\n }\n } else {\n unknownCount++;\n const personInfo = `I see an unidentified person who has been here for ${durationStr}.`;\n identifications.push(personInfo);\n\n if (person.attributes.faceId) {\n identifications.push(\n \"I've captured their face profile but they haven't been named yet.\",\n );\n }\n }\n }\n\n const recentlyLeft = entityTracker.getRecentlyLeft();\n if (recentlyLeft.length > 0) {\n identifications.push(\"\\nRecently departed:\");\n for (const { entity, leftAt } of recentlyLeft) {\n if (entity.entityType === \"person\" && entity.attributes.name) {\n const timeAgo = Date.now() - leftAt;\n const timeStr =\n timeAgo < 60000\n ? `${Math.round(timeAgo / 1000)} seconds ago`\n : `${Math.round(timeAgo / 60000)} minutes ago`;\n identifications.push(`${entity.attributes.name} left ${timeStr}.`);\n }\n }\n }\n\n const thought = `Identified ${recognizedCount} known people and ${unknownCount} unknown people.`;\n const text = identifications.join(\" \");\n\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n\n if (callback) {\n await callback({\n thought,\n text,\n actions: [\"VISION\"],\n data: {\n identifications: people.slice(0, MAX_VISION_ENTITIES).map((p) => ({\n id: p.id,\n entityType: p.entityType,\n name: p.attributes.name || undefined,\n })),\n },\n });\n }\n return {\n success: true,\n text,\n values: { recognizedCount, unknownCount },\n data: {\n actionName: \"VISION\",\n op: \"identify_person\",\n recognizedCount,\n unknownCount,\n },\n };\n } catch (error) {\n logger.error(\"[VISION/identify_person] Error:\", error);\n const thought = \"Failed to identify people.\";\n const text = `Sorry, I couldn't identify people: ${error instanceof Error ? error.message : \"Unknown error\"}`;\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n error: error instanceof Error ? error.message : String(error),\n data: { actionName: \"VISION\", op: \"identify_person\" },\n };\n }\n}\n\nasync function runTrackEntity(\n runtime: IAgentRuntime,\n message: Memory,\n callback?: HandlerCallback,\n): Promise<ActionResult> {\n try {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService) {\n const thought = \"Vision service is not available.\";\n const text =\n \"I cannot track entities because the vision service is not available.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n data: { actionName: \"VISION\", op: \"track_entity\" },\n };\n }\n\n const scene = await withVisionTimeout(\n visionService.getSceneDescription(),\n \"vision scene description\",\n );\n\n if (!scene) {\n const thought = \"No scene available for tracking.\";\n const text =\n \"I need a moment to process the visual scene before I can track entities.\";\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n data: { actionName: \"VISION\", op: \"track_entity\" },\n };\n }\n\n const entityTracker = visionService.getEntityTracker();\n await entityTracker.updateEntities(\n scene.objects.slice(0, MAX_VISION_ENTITIES),\n scene.people.slice(0, MAX_VISION_ENTITIES),\n undefined,\n runtime,\n );\n const stats = entityTracker.getStatistics();\n\n const thought = `Tracking ${stats.activeEntities} entities in the scene.`;\n const summary = [\n `I'm now tracking ${stats.activeEntities} entities in the scene`,\n `(${stats.people} people, ${stats.objects} objects).`,\n \"The visual tracking system will maintain persistent IDs for all entities\",\n \"and notify you of significant changes.\",\n ];\n const responseText = summary.join(\" \");\n\n await saveExecutionRecord(runtime, message, thought, responseText, [\n \"VISION\",\n ]);\n\n if (callback) {\n await callback({\n thought,\n text: responseText,\n actions: [\"VISION\"],\n data: { entities: stats.activeEntities },\n });\n }\n\n logger.info(\n `[VISION/track_entity] Tracking ${stats.activeEntities} entities`,\n );\n return {\n success: true,\n text: responseText,\n values: {\n activeEntities: stats.activeEntities,\n people: stats.people,\n objects: stats.objects,\n },\n data: {\n actionName: \"VISION\",\n op: \"track_entity\",\n activeEntities: stats.activeEntities,\n people: stats.people,\n objects: stats.objects,\n },\n };\n } catch (error) {\n logger.error(\"[VISION/track_entity] Error:\", error);\n const thought = \"Failed to track entities.\";\n const text = `Sorry, I couldn't track entities: ${error instanceof Error ? error.message : \"Unknown error\"}`;\n await saveExecutionRecord(runtime, message, thought, text, [\"VISION\"]);\n if (callback) {\n await callback({ thought, text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n error: error instanceof Error ? error.message : String(error),\n data: { actionName: \"VISION\", op: \"track_entity\" },\n };\n }\n}\n\nexport const visionAction: Action = {\n name: \"VISION\",\n contexts: [...ALL_VISION_CONTEXTS],\n contextGate: { anyOf: [...ALL_VISION_CONTEXTS] },\n roleGate: { minRole: \"USER\" },\n similes: [\n \"DESCRIBE_SCENE\",\n \"CAPTURE_IMAGE\",\n \"SET_VISION_MODE\",\n \"NAME_ENTITY\",\n \"IDENTIFY_PERSON\",\n \"TRACK_ENTITY\",\n \"ANALYZE_SCENE\",\n \"WHAT_DO_YOU_SEE\",\n \"VISION_CHECK\",\n \"LOOK_AROUND\",\n \"TAKE_PHOTO\",\n \"SCREENSHOT\",\n \"CAPTURE_FRAME\",\n \"TAKE_PICTURE\",\n ],\n description:\n \"Camera and screen vision: describe the current scene, capture an image, switch vision mode (off/camera/screen/both), name a visible entity, identify a person, or start tracking an entity. The op is inferred from the message text when not explicitly provided.\",\n descriptionCompressed:\n \"Vision: describe / capture / set_mode / name_entity / identify_person / track_entity.\",\n parameters: [\n {\n name: \"subaction\",\n description:\n \"Operation to perform: describe, capture, set_mode, name_entity, identify_person, or track_entity. Inferred from message text when omitted.\",\n required: false,\n schema: { type: \"string\", enum: [...VISION_OPS] },\n },\n {\n name: \"detailLevel\",\n description:\n \"For op=describe: 'summary' to omit object/person breakdowns, 'detailed' for the full breakdown.\",\n required: false,\n schema: {\n type: \"string\",\n enum: [\"summary\", \"detailed\"],\n default: \"detailed\",\n },\n },\n {\n name: \"mode\",\n description:\n \"For op=set_mode: vision mode to set: off, camera, screen, or both.\",\n required: false,\n schema: { type: \"string\", enum: [\"off\", \"camera\", \"screen\", \"both\"] },\n },\n {\n name: \"name\",\n description:\n \"For op=name_entity: the name to assign to the most relevant visible person or object.\",\n required: false,\n schema: { type: \"string\" },\n },\n {\n name: \"targetHint\",\n description:\n \"For op=name_entity or op=identify_person: optional phrase describing which visible entity to focus on.\",\n required: false,\n schema: { type: \"string\" },\n },\n {\n name: \"description\",\n description:\n \"For op=track_entity: optional description of the visible entity to prioritize for tracking.\",\n required: false,\n schema: { type: \"string\" },\n },\n {\n name: \"includeUnknown\",\n description:\n \"For op=identify_person: whether to mention unidentified people in the response.\",\n required: false,\n schema: { type: \"boolean\", default: true },\n },\n ],\n validate: async (\n runtime: IAgentRuntime,\n _message: Memory,\n state?: State,\n options?: Record<string, unknown>,\n ): Promise<boolean> => {\n if (!visionServiceIsActive(runtime)) {\n // set_mode does not require active vision; allow if service is registered.\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) return false;\n }\n const params = readActionParams(options);\n return (\n selectedContextMatches(state, ALL_VISION_CONTEXTS) ||\n typeof params.op === \"string\"\n );\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n _options?: Record<string, unknown>,\n callback?: HandlerCallback,\n _responses?: Memory[],\n ): Promise<ActionResult> => {\n const params = readActionParams(_options);\n const explicitOp = normalizeOp(params.op ?? params.subaction);\n const inferredOp =\n explicitOp ?? inferOpFromMessage(message.content?.text ?? \"\");\n\n if (!inferredOp) {\n const text = `VISION could not determine the operation. Specify one of: ${VISION_OPS.join(\", \")}.`;\n if (callback) {\n await callback({ text, actions: [\"VISION\"] });\n }\n return {\n success: false,\n text,\n values: { error: \"MISSING\" },\n data: {\n actionName: \"VISION\",\n availableOps: VISION_OPS,\n },\n };\n }\n\n switch (inferredOp) {\n case \"describe\":\n return runDescribe(runtime, message, params, callback);\n case \"capture\":\n return runCapture(runtime, message, callback);\n case \"set_mode\":\n return runSetMode(runtime, message, params, callback);\n case \"name_entity\":\n return runNameEntity(runtime, message, params, callback);\n case \"identify_person\":\n return runIdentifyPerson(runtime, message, callback);\n case \"track_entity\":\n return runTrackEntity(runtime, message, callback);\n }\n },\n examples: [\n [\n { name: \"{{user}}\", content: { text: \"what do you see?\" } },\n {\n name: \"{{agent}}\",\n content: {\n actions: [\"VISION\"],\n thought: \"The user wants to know what I can see through my camera.\",\n text: \"I see a room with a desk and computer setup. There are 2 people, one is sitting and one is standing.\",\n },\n },\n ],\n [\n { name: \"{{user}}\", content: { text: \"take a photo\" } },\n {\n name: \"{{agent}}\",\n content: {\n actions: [\"VISION\"],\n thought: \"The user wants me to capture an image from the camera.\",\n text: \"I've captured an image from the camera.\",\n },\n },\n ],\n [\n { name: \"{{user}}\", content: { text: \"set vision mode to screen\" } },\n {\n name: \"{{agent}}\",\n content: {\n actions: [\"VISION\"],\n thought: \"The user wants to switch to screen vision mode.\",\n text: \"Vision mode set to SCREEN only. I will analyze what's on your screen.\",\n },\n },\n ],\n [\n {\n name: \"{{user}}\",\n content: { text: \"the person wearing the blue shirt is named Alice\" },\n },\n {\n name: \"{{agent}}\",\n content: {\n actions: [\"VISION\"],\n text: \"I've identified the person in the blue shirt as Alice. I'll remember them for future interactions.\",\n },\n },\n ],\n [\n {\n name: \"{{user}}\",\n content: { text: \"who is the person in front of you?\" },\n },\n {\n name: \"{{agent}}\",\n content: {\n actions: [\"VISION\"],\n text: \"That's Alice. I last saw her about 5 minutes ago.\",\n },\n },\n ],\n [\n {\n name: \"{{user}}\",\n content: { text: \"track the person wearing the red shirt\" },\n },\n {\n name: \"{{agent}}\",\n content: {\n actions: [\"VISION\"],\n text: \"I'm now tracking the person in the red shirt.\",\n },\n },\n ],\n ] as ActionExample[][],\n};\n",
7
+ "export const VisionServiceType = {\n VISION: \"VISION\" as const,\n};\n\ndeclare module \"@elizaos/core\" {\n interface ServiceTypeRegistry {\n VISION: \"VISION\";\n }\n}\n\nexport interface CameraInfo {\n id: string;\n name: string;\n connected: boolean;\n}\n\nexport interface SceneDescription {\n timestamp: number;\n description: string;\n objects: DetectedObject[];\n people: PersonInfo[];\n sceneChanged: boolean;\n changePercentage: number;\n audioTranscription?: string;\n}\n\nexport interface DetectedObject {\n id: string;\n type: string;\n confidence: number;\n boundingBox: BoundingBox;\n}\n\nexport interface PersonInfo {\n id: string;\n pose: \"sitting\" | \"standing\" | \"lying\" | \"unknown\";\n facing: \"camera\" | \"away\" | \"left\" | \"right\" | \"unknown\";\n confidence: number;\n boundingBox: BoundingBox;\n keypoints?: Array<{\n part: string;\n position: { x: number; y: number };\n score: number;\n }>;\n}\n\nexport interface BoundingBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface VisionFrame {\n timestamp: number;\n width: number;\n height: number;\n data: Buffer;\n format: \"rgb\" | \"rgba\" | \"jpeg\" | \"png\";\n}\n\nexport enum VisionMode {\n OFF = \"OFF\",\n CAMERA = \"CAMERA\",\n SCREEN = \"SCREEN\",\n BOTH = \"BOTH\",\n}\n\n// Screen capture types\nexport interface ScreenCapture {\n timestamp: number;\n width: number;\n height: number;\n data: Buffer;\n tiles: ScreenTile[];\n}\n\nexport interface ScreenTile {\n id: string;\n row: number;\n col: number;\n x: number;\n y: number;\n width: number;\n height: number;\n data?: Buffer;\n analysis?: TileAnalysis;\n}\n\nexport interface TileAnalysis {\n timestamp: number;\n florence2?: Florence2Result;\n ocr?: OCRResult;\n objects?: DetectedObject[];\n text?: string;\n summary?: string;\n}\n\nexport interface Florence2Result {\n caption?: string;\n objects?: Array<{\n label: string;\n bbox: BoundingBox;\n confidence: number;\n }>;\n regions?: Array<{\n description: string;\n bbox: BoundingBox;\n }>;\n tags?: string[];\n}\n\nexport interface OCRResult {\n text: string;\n blocks: Array<{\n text: string;\n bbox: BoundingBox;\n confidence: number;\n words?: Array<{\n text: string;\n bbox: BoundingBox;\n confidence: number;\n }>;\n }>;\n fullText: string;\n}\n\nexport interface EnhancedSceneDescription extends SceneDescription {\n screenCapture?: ScreenCapture;\n screenAnalysis?: {\n fullScreenOCR?: string;\n activeTile?: TileAnalysis;\n gridSummary?: string;\n focusedApp?: string;\n uiElements?: Array<{\n type: string;\n text: string;\n position: BoundingBox;\n }>;\n };\n}\n\nexport interface VisionConfig {\n cameraName?: string;\n pixelChangeThreshold?: number;\n updateInterval?: number;\n enablePoseDetection?: boolean;\n enableObjectDetection?: boolean;\n tfUpdateInterval?: number;\n vlmUpdateInterval?: number;\n tfChangeThreshold?: number;\n vlmChangeThreshold?: number;\n visionMode?: VisionMode;\n screenCaptureInterval?: number;\n tileSize?: number;\n tileProcessingOrder?: \"sequential\" | \"priority\" | \"random\";\n ocrEnabled?: boolean;\n florence2Enabled?: boolean;\n screenRegion?: {\n x: number;\n y: number;\n width: number;\n height: number;\n };\n displayIndex?: number;\n captureAllDisplays?: boolean;\n targetScreenFPS?: number;\n textRegions?: Array<{\n x: number;\n y: number;\n width: number;\n height: number;\n }>;\n}\n\nexport interface TrackedEntity {\n id: string;\n entityType: \"person\" | \"object\" | \"pet\";\n firstSeen: number;\n lastSeen: number;\n lastPosition: BoundingBox;\n appearances: EntityAppearance[];\n attributes: EntityAttributes;\n worldId?: string;\n roomId?: string;\n}\n\nexport interface EntityAppearance {\n timestamp: number;\n boundingBox: BoundingBox;\n confidence: number;\n embedding?: number[]; // Face embedding for person recognition\n keypoints?: Array<{\n part: string;\n position: { x: number; y: number };\n score: number;\n }>;\n}\n\nexport interface EntityAttributes {\n [key: string]:\n | string\n | number\n | boolean\n | null\n | undefined\n | string[]\n | number[];\n name?: string;\n faceEmbedding?: number[];\n faceId?: string;\n clothing?: string[];\n hairColor?: string;\n accessories?: string[];\n\n // For objects\n objectType?: string;\n color?: string;\n size?: \"small\" | \"medium\" | \"large\";\n description?: string;\n tags?: string[];\n}\n\nexport interface FaceLibrary {\n faces: Map<string, FaceProfile>;\n embeddings: Map<string, number[][]>; // Multiple embeddings per profile\n}\n\nexport interface FaceProfile {\n id: string;\n name?: string;\n embeddings: number[][]; // Multiple embeddings for better recognition\n firstSeen: number;\n lastSeen: number;\n seenCount: number;\n attributes?: {\n age?: string;\n gender?: string;\n emotion?: string;\n };\n}\n\nexport interface WorldState {\n worldId: string;\n entities: Map<string, TrackedEntity>;\n lastUpdate: number;\n activeEntities: string[];\n recentlyLeft: Array<{\n entityId: string;\n leftAt: number;\n lastPosition: BoundingBox;\n }>;\n}\n",
8
+ "import {\n type IAgentRuntime,\n logger,\n type Memory,\n type Provider,\n type State,\n} from \"@elizaos/core\";\nimport type { VisionService } from \"./service\";\nimport type {\n BoundingBox,\n EnhancedSceneDescription,\n EntityAttributes,\n} from \"./types\";\n\nconst MAX_VISION_OBJECTS_IN_STATE = 50;\nconst MAX_VISION_PEOPLE_IN_STATE = 25;\nconst MAX_TRACKED_ENTITIES_IN_STATE = 25;\n\nexport const visionProvider: Provider = {\n name: \"VISION_PERCEPTION\",\n description:\n \"Provides current visual perception data including scene description, detected objects, people, and entity tracking. This provider is always active and provides real-time visual awareness.\",\n position: 99,\n contexts: [\"media\", \"browser\"],\n contextGate: { anyOf: [\"media\", \"browser\"] },\n cacheStable: false,\n cacheScope: \"turn\",\n dynamic: false,\n get: async (runtime: IAgentRuntime, message: Memory, _state: State) => {\n const visionService = runtime.getService<VisionService>(\"VISION\");\n\n if (!visionService) {\n logger.warn(\"[visionProvider] VisionService not found.\");\n return {\n values: {\n visionAvailable: false,\n sceneDescription: \"Vision service is not available.\",\n cameraStatus: \"No camera connected\",\n },\n text: JSON.stringify(\n {\n visual_perception: {\n visionAvailable: false,\n sceneDescription: \"Vision service is not available.\",\n cameraStatus: \"No camera connected\",\n },\n },\n null,\n 2,\n ),\n data: { hasVision: false },\n };\n }\n\n try {\n const sceneDescription =\n (await visionService.getEnhancedSceneDescription()) ||\n (await visionService.getSceneDescription());\n const cameraInfo = visionService.getCameraInfo();\n const isActive = visionService.isActive();\n const visionMode = visionService.getVisionMode();\n const screenCapture = await visionService.getScreenCapture();\n const _worldId = message.worldId || \"default-world\";\n const entityTracker = visionService.getEntityTracker();\n\n let entityData: {\n activeEntities: Array<{\n id: string;\n type: \"person\" | \"object\" | \"pet\";\n name: string | undefined;\n firstSeen: number;\n duration: number;\n position: BoundingBox;\n attributes: EntityAttributes;\n }>;\n recentlyLeft: Array<{\n id: string;\n name: string | undefined;\n leftAt: number;\n timeAgo: number;\n }>;\n statistics: {\n totalEntities: number;\n activeEntities: number;\n recentlyLeft: number;\n people: number;\n objects: number;\n };\n } | null = null;\n\n if (sceneDescription && entityTracker) {\n await entityTracker.updateEntities(\n sceneDescription.objects,\n sceneDescription.people,\n undefined,\n runtime,\n );\n\n const activeEntities = entityTracker.getActiveEntities();\n const recentlyLeft = entityTracker.getRecentlyLeft();\n const stats = entityTracker.getStatistics();\n\n entityData = {\n activeEntities: activeEntities\n .slice(0, MAX_TRACKED_ENTITIES_IN_STATE)\n .map((e) => ({\n id: e.id,\n type: e.entityType,\n name: e.attributes.name,\n firstSeen: e.firstSeen,\n duration: Date.now() - e.firstSeen,\n position: e.lastPosition,\n attributes: e.attributes,\n })),\n recentlyLeft: recentlyLeft\n .slice(0, MAX_TRACKED_ENTITIES_IN_STATE)\n .map(({ entity, leftAt }) => ({\n id: entity.id,\n name: entity.attributes.name,\n leftAt,\n timeAgo: Date.now() - leftAt,\n })),\n statistics: stats,\n };\n }\n\n let perceptionText = \"\";\n let values = {};\n let data = {};\n\n if (!isActive) {\n perceptionText = `Vision mode: ${visionMode}\\n`;\n if (visionMode === \"OFF\") {\n perceptionText += \"Vision is disabled.\";\n } else {\n perceptionText += \"Vision service is initializing...\";\n }\n\n values = {\n visionAvailable: false,\n visionMode,\n sceneDescription: \"Vision not active\",\n cameraStatus: cameraInfo\n ? `Camera \"${cameraInfo.name}\" detected but not active`\n : \"No camera\",\n };\n } else {\n perceptionText = `Vision mode: ${visionMode}\\n\\n`;\n\n if (\n (visionMode === \"CAMERA\" || visionMode === \"BOTH\") &&\n sceneDescription\n ) {\n const ageInSeconds = (Date.now() - sceneDescription.timestamp) / 1000;\n const secondsAgo = Math.round(ageInSeconds);\n\n perceptionText += `Camera view (${secondsAgo}s ago):\\n${sceneDescription.description}`;\n\n if (sceneDescription.people.length > 0) {\n perceptionText += `\\n\\nPeople detected: ${sceneDescription.people.length}`;\n const poses = sceneDescription.people\n .map((p) => p.pose)\n .filter((p) => p !== \"unknown\");\n const facings = sceneDescription.people\n .map((p) => p.facing)\n .filter((f) => f !== \"unknown\");\n\n if (poses.length > 0) {\n const poseCounts = poses.reduce(\n (acc, pose) => {\n acc[pose] = (acc[pose] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>,\n );\n perceptionText += `\\n Poses: ${Object.entries(poseCounts)\n .map(([pose, count]) => `${count} ${pose}`)\n .join(\", \")}`;\n }\n\n if (facings.length > 0) {\n const facingCounts = facings.reduce(\n (acc, facing) => {\n acc[facing] = (acc[facing] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>,\n );\n perceptionText += `\\n Facing: ${Object.entries(facingCounts)\n .map(([facing, count]) => `${count} facing ${facing}`)\n .join(\", \")}`;\n }\n }\n\n if (sceneDescription.objects.length > 0) {\n const objectTypes = sceneDescription.objects\n .slice(0, MAX_VISION_OBJECTS_IN_STATE)\n .map((o) => o.type);\n const uniqueObjects = [...new Set(objectTypes)];\n perceptionText += `\\n\\nObjects detected: ${uniqueObjects.join(\", \")}`;\n }\n\n if (sceneDescription.sceneChanged) {\n perceptionText += `\\n\\nScene change: ${sceneDescription.changePercentage.toFixed(1)}% of pixels changed`;\n }\n\n if (entityData) {\n if (entityData.activeEntities.length > 0) {\n perceptionText += \"\\n\\nCurrently tracking:\";\n for (const entity of entityData.activeEntities) {\n const name = entity.name || `Unknown ${entity.type}`;\n const duration =\n entity.duration < 60000\n ? `${Math.round(entity.duration / 1000)}s`\n : `${Math.round(entity.duration / 60000)}m`;\n perceptionText += `\\n- ${name} (present for ${duration})`;\n }\n }\n\n if (entityData.recentlyLeft.length > 0) {\n perceptionText += \"\\n\\nRecently left:\";\n for (const departed of entityData.recentlyLeft) {\n const name = departed.name || \"Unknown person\";\n const timeStr =\n departed.timeAgo < 60000\n ? `${Math.round(departed.timeAgo / 1000)}s ago`\n : `${Math.round(departed.timeAgo / 60000)}m ago`;\n perceptionText += `\\n- ${name} left ${timeStr}`;\n }\n }\n }\n }\n\n if (\n (visionMode === \"SCREEN\" || visionMode === \"BOTH\") &&\n screenCapture\n ) {\n const screenAge = (Date.now() - screenCapture.timestamp) / 1000;\n const screenSecondsAgo = Math.round(screenAge);\n\n if (visionMode === \"BOTH\") {\n perceptionText += \"\\n\\n---\\n\\n\";\n }\n\n perceptionText += `Screen capture (${screenSecondsAgo}s ago):\\n`;\n perceptionText += `Resolution: ${screenCapture.width}x${screenCapture.height}\\n`;\n\n const enhanced = sceneDescription as EnhancedSceneDescription;\n if (enhanced?.screenAnalysis) {\n const tileAnalysis = enhanced.screenAnalysis.activeTile;\n if (tileAnalysis) {\n if (tileAnalysis.summary) {\n perceptionText += `\\nActive area: ${tileAnalysis.summary}`;\n }\n\n if (tileAnalysis.text) {\n perceptionText += `\\n\\nVisible text:\\n\"${tileAnalysis.text.substring(0, 200)}${tileAnalysis.text.length > 200 ? \"...\" : \"\"}\"`;\n }\n\n if (tileAnalysis.objects && tileAnalysis.objects.length > 0) {\n const uiElements = tileAnalysis.objects.map(\n (o) => (o as { type?: string }).type || \"unknown\",\n );\n const uniqueElements = [...new Set(uiElements)];\n perceptionText += `\\n\\nUI elements: ${uniqueElements.join(\", \")}`;\n }\n }\n\n if (enhanced.screenAnalysis.focusedApp) {\n perceptionText += `\\n\\nActive application: ${enhanced.screenAnalysis.focusedApp}`;\n }\n }\n }\n\n values = {\n visionAvailable: true,\n visionMode,\n sceneDescription: sceneDescription?.description || \"Processing...\",\n cameraStatus: cameraInfo\n ? `Connected to ${cameraInfo.name}`\n : \"No camera\",\n cameraId: cameraInfo?.id,\n peopleCount: sceneDescription?.people.length || 0,\n objectCount: sceneDescription?.objects.length || 0,\n sceneAge: sceneDescription\n ? Math.round((Date.now() - sceneDescription.timestamp) / 1000)\n : null,\n lastChange: sceneDescription?.sceneChanged\n ? sceneDescription.changePercentage\n : 0,\n hasScreenCapture: !!screenCapture,\n screenResolution: screenCapture\n ? `${screenCapture.width}x${screenCapture.height}`\n : null,\n activeEntities: entityData?.activeEntities || [],\n recentlyLeft: entityData?.recentlyLeft || [],\n entityStatistics: entityData?.statistics || null,\n };\n\n data = {\n objects:\n sceneDescription?.objects.slice(0, MAX_VISION_OBJECTS_IN_STATE) ||\n [],\n people:\n sceneDescription?.people.slice(0, MAX_VISION_PEOPLE_IN_STATE) || [],\n screenCapture: screenCapture || null,\n enhancedData:\n (sceneDescription as EnhancedSceneDescription)?.screenAnalysis ||\n null,\n trackedEntities: entityData?.activeEntities || [],\n worldState: entityData || null,\n };\n }\n\n return {\n values,\n text: JSON.stringify(\n {\n visual_perception: {\n summary: perceptionText,\n ...values,\n },\n },\n null,\n 2,\n ),\n data,\n };\n } catch (error) {\n return {\n values: {\n visionAvailable: false,\n error: error instanceof Error ? error.message : String(error),\n },\n text: JSON.stringify(\n {\n visual_perception: {\n visionAvailable: false,\n error: error instanceof Error ? error.message : String(error),\n },\n },\n null,\n 2,\n ),\n data: {\n hasVision: false,\n error: error instanceof Error ? error.message : String(error),\n },\n };\n }\n },\n};\n",
9
+ "// Vision service for camera integration and scene analysis\n\nimport { exec } from \"node:child_process\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport {\n type IAgentRuntime,\n logger,\n ModelType,\n recordLlmCall,\n Service,\n type ServiceTypeName,\n withStandaloneTrajectory,\n} from \"@elizaos/core\";\nimport sharp from \"sharp\";\nimport { AudioCaptureService, type AudioConfig } from \"./audio-capture\";\nimport {\n StreamingAudioCaptureService,\n type StreamingAudioConfig,\n} from \"./audio-capture-stream\";\nimport { EntityTracker } from \"./entity-tracker\";\nimport { FaceRecognition } from \"./face-recognition\";\nimport { Florence2Model } from \"./florence2-model\";\nimport { OCRService } from \"./ocr-service\";\nimport { ScreenCaptureService } from \"./screen-capture\";\nimport { getTestImage } from \"./test-input\";\nimport {\n type BoundingBox,\n type CameraInfo,\n type DetectedObject,\n type EnhancedSceneDescription,\n type PersonInfo,\n type SceneDescription,\n type ScreenCapture,\n type ScreenTile,\n type TileAnalysis,\n type VisionConfig,\n type VisionFrame,\n VisionMode,\n VisionServiceType,\n} from \"./types\";\nimport { VisionModels } from \"./vision-models\";\nimport { VisionWorkerManager } from \"./vision-worker-manager\";\n\nconst execAsync = promisify(exec);\nconst SCENE_DESCRIPTION_PROMPT = JSON.stringify(\n {\n task: \"describe_visual_scene\",\n instructions: [\n \"Describe visible people, objects, UI, text, and notable scene changes.\",\n \"Keep the answer concise and factual.\",\n ],\n },\n null,\n 2,\n);\n\ninterface CameraDevice {\n id: string;\n name: string;\n capture: () => Promise<Buffer>;\n}\n\nexport class VisionService extends Service {\n static override serviceType: ServiceTypeName = VisionServiceType.VISION;\n override capabilityDescription =\n \"Provides visual perception through camera integration and scene analysis.\";\n\n private visionConfig: VisionConfig;\n private camera: CameraDevice | null = null;\n private lastFrame: VisionFrame | null = null;\n private lastSceneDescription: SceneDescription | null = null;\n private frameProcessingInterval: NodeJS.Timeout | null = null;\n private screenProcessingInterval: NodeJS.Timeout | null = null;\n private isProcessing = false;\n private isProcessingScreen = false;\n private visionModels: VisionModels;\n private faceRecognition: FaceRecognition;\n private entityTracker: EntityTracker;\n private audioCapture: AudioCaptureService | null = null;\n private streamingAudioCapture: StreamingAudioCaptureService | null = null;\n\n // Screen vision components\n private screenCapture: ScreenCaptureService;\n private florence2: Florence2Model;\n private ocrService: OCRService;\n private lastScreenCapture: ScreenCapture | null = null;\n private lastEnhancedScene: EnhancedSceneDescription | null = null;\n\n // Worker manager for high-FPS processing\n private workerManager: VisionWorkerManager | null = null;\n\n // Add tracking for last update times\n private lastTfUpdateTime = 0;\n private lastVlmUpdateTime = 0;\n private lastTfDescription = \"\";\n\n // Default configuration\n private readonly DEFAULT_CONFIG: VisionConfig = {\n pixelChangeThreshold: 50, // 50% change required for VLM update\n updateInterval: 100, // Process frames every 100ms\n enablePoseDetection: false,\n enableObjectDetection: false,\n tfUpdateInterval: 1000, // TensorFlow update every 1 second\n vlmUpdateInterval: 10000, // VLM update every 10 seconds\n tfChangeThreshold: 10, // 10% change triggers TF update\n vlmChangeThreshold: 50, // 50% change triggers VLM update\n visionMode: VisionMode.CAMERA, // Default to camera only\n screenCaptureInterval: 2000, // Screen capture every 2 seconds\n tileSize: 256,\n tileProcessingOrder: \"priority\",\n ocrEnabled: true,\n florence2Enabled: true,\n };\n\n constructor(runtime: IAgentRuntime) {\n super(runtime);\n\n // Load configuration from runtime settings\n this.visionConfig = this.parseConfig(runtime);\n\n // Initialize vision models\n this.visionModels = new VisionModels();\n\n // Initialize face recognition\n this.faceRecognition = new FaceRecognition();\n\n // Initialize entity tracker\n const worldIdValue = runtime.getSetting(\"WORLD_ID\");\n const worldId =\n typeof worldIdValue === \"string\" ? worldIdValue : \"default-world\";\n this.entityTracker = new EntityTracker(worldId);\n\n // Initialize screen capture\n this.screenCapture = new ScreenCaptureService(this.visionConfig);\n\n // Initialize Florence-2\n this.florence2 = new Florence2Model();\n\n // Initialize OCR service\n this.ocrService = new OCRService();\n\n logger.info(\n \"[VisionService] Constructed with config:\",\n JSON.stringify(this.visionConfig),\n );\n }\n\n private parseConfig(runtime: IAgentRuntime): VisionConfig {\n const getSettingString = (key: string): string | undefined => {\n const value = runtime.getSetting(key);\n return value === true || value === false\n ? String(value)\n : typeof value === \"string\"\n ? value\n : typeof value === \"number\"\n ? String(value)\n : undefined;\n };\n\n return {\n ...this.DEFAULT_CONFIG,\n cameraName:\n getSettingString(\"CAMERA_NAME\") ||\n getSettingString(\"VISION_CAMERA_NAME\"),\n pixelChangeThreshold:\n Number(\n runtime.getSetting(\"PIXEL_CHANGE_THRESHOLD\") ||\n runtime.getSetting(\"VISION_PIXEL_CHANGE_THRESHOLD\"),\n ) || this.DEFAULT_CONFIG.pixelChangeThreshold,\n enableObjectDetection:\n runtime.getSetting(\"ENABLE_OBJECT_DETECTION\") === \"true\" ||\n runtime.getSetting(\"VISION_ENABLE_OBJECT_DETECTION\") === \"true\",\n enablePoseDetection:\n runtime.getSetting(\"ENABLE_POSE_DETECTION\") === \"true\" ||\n runtime.getSetting(\"VISION_ENABLE_POSE_DETECTION\") === \"true\",\n tfUpdateInterval:\n Number(\n runtime.getSetting(\"TF_UPDATE_INTERVAL\") ||\n runtime.getSetting(\"VISION_TF_UPDATE_INTERVAL\"),\n ) || this.DEFAULT_CONFIG.tfUpdateInterval,\n vlmUpdateInterval:\n Number(\n runtime.getSetting(\"VLM_UPDATE_INTERVAL\") ||\n runtime.getSetting(\"VISION_VLM_UPDATE_INTERVAL\"),\n ) || this.DEFAULT_CONFIG.vlmUpdateInterval,\n tfChangeThreshold:\n Number(\n runtime.getSetting(\"TF_CHANGE_THRESHOLD\") ||\n runtime.getSetting(\"VISION_TF_CHANGE_THRESHOLD\"),\n ) || this.DEFAULT_CONFIG.tfChangeThreshold,\n vlmChangeThreshold:\n Number(\n runtime.getSetting(\"VLM_CHANGE_THRESHOLD\") ||\n runtime.getSetting(\"VISION_VLM_CHANGE_THRESHOLD\"),\n ) || this.DEFAULT_CONFIG.vlmChangeThreshold,\n visionMode:\n (getSettingString(\"VISION_MODE\") as VisionMode) ||\n this.DEFAULT_CONFIG.visionMode,\n screenCaptureInterval:\n Number(\n runtime.getSetting(\"SCREEN_CAPTURE_INTERVAL\") ||\n runtime.getSetting(\"VISION_SCREEN_CAPTURE_INTERVAL\"),\n ) || this.DEFAULT_CONFIG.screenCaptureInterval,\n ocrEnabled:\n getSettingString(\"OCR_ENABLED\") === \"true\" ||\n getSettingString(\"VISION_OCR_ENABLED\") === \"true\",\n florence2Enabled:\n getSettingString(\"FLORENCE2_ENABLED\") === \"true\" ||\n getSettingString(\"VISION_FLORENCE2_ENABLED\") === \"true\",\n };\n }\n\n static async start(runtime: IAgentRuntime): Promise<VisionService> {\n const service = new VisionService(runtime);\n await service.initialize();\n return service;\n }\n\n private async checkCameraTools(): Promise<{\n available: boolean;\n tool: string;\n }> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // Check if imagesnap is installed\n await execAsync(\"which imagesnap\");\n return { available: true, tool: \"imagesnap\" };\n } else if (platform === \"linux\") {\n // Check if fswebcam is installed\n await execAsync(\"which fswebcam\");\n return { available: true, tool: \"fswebcam\" };\n } else if (platform === \"win32\") {\n // Check if ffmpeg is available\n await execAsync(\"where ffmpeg\");\n return { available: true, tool: \"ffmpeg\" };\n }\n return { available: false, tool: \"none\" };\n } catch (_error) {\n // Tool not found\n return { available: false, tool: \"none\" };\n }\n }\n\n private async initialize(): Promise<void> {\n try {\n // Initialize vision models if enabled\n const useEnhancedModels =\n this.visionConfig.enableObjectDetection ||\n this.visionConfig.enablePoseDetection;\n\n if (useEnhancedModels) {\n try {\n // Try to initialize TensorFlow models first\n await this.visionModels.initialize({\n enableObjectDetection:\n this.visionConfig.enableObjectDetection || false,\n enablePoseDetection: this.visionConfig.enablePoseDetection || false,\n });\n logger.info(\n \"[VisionService] Using TensorFlow.js models for advanced detection\",\n );\n } catch (_tfError) {\n logger.warn(\n \"[VisionService] TensorFlow.js not available, falling back to enhanced heuristics\",\n );\n // Fall back to enhanced heuristics\n await this.visionModels.initialize({\n enableObjectDetection:\n this.visionConfig.enableObjectDetection || false,\n enablePoseDetection: this.visionConfig.enablePoseDetection || false,\n });\n logger.info(\n \"[VisionService] Using enhanced heuristics for detection\",\n );\n }\n }\n\n // Initialize screen vision if enabled\n if (\n this.visionConfig.visionMode === VisionMode.SCREEN ||\n this.visionConfig.visionMode === VisionMode.BOTH\n ) {\n await this.initializeScreenVision();\n }\n\n // Initialize camera if enabled\n if (\n this.visionConfig.visionMode === VisionMode.CAMERA ||\n this.visionConfig.visionMode === VisionMode.BOTH\n ) {\n await this.initializeCameraVision();\n }\n\n // Initialize audio capture if enabled\n await this.initializeAudioCapture();\n\n // Start processing based on mode\n this.startProcessing();\n } catch (error) {\n logger.error(\"[VisionService] Failed to initialize:\", error);\n }\n }\n\n private async initializeScreenVision(): Promise<void> {\n try {\n logger.info(\"[VisionService] Initializing screen vision...\");\n\n // Check if we should use worker threads for high-FPS processing\n const useWorkers =\n this.visionConfig.targetScreenFPS &&\n this.visionConfig.targetScreenFPS > 10;\n\n if (useWorkers) {\n // Initialize worker manager for high-FPS processing\n logger.info(\n \"[VisionService] Initializing worker threads for high-FPS processing...\",\n );\n this.workerManager = new VisionWorkerManager(this.visionConfig);\n await this.workerManager.initialize();\n logger.info(\"[VisionService] Worker threads initialized\");\n } else {\n // Initialize standard components\n // Initialize Florence-2 if enabled\n if (this.visionConfig.florence2Enabled) {\n await this.florence2.initialize();\n }\n\n // Initialize OCR if enabled\n if (this.visionConfig.ocrEnabled) {\n await this.ocrService.initialize();\n }\n }\n\n // Get screen info\n const screenInfo = await this.screenCapture.getScreenInfo();\n if (screenInfo) {\n logger.info(\n `[VisionService] Screen resolution: ${screenInfo.width}x${screenInfo.height}`,\n );\n }\n\n logger.info(\"[VisionService] Screen vision initialized\");\n } catch (error) {\n logger.error(\n \"[VisionService] Failed to initialize screen vision:\",\n error,\n );\n }\n }\n\n private async initializeCameraVision(): Promise<void> {\n // Check if camera tools are available\n const toolCheck = await this.checkCameraTools();\n if (!toolCheck.available) {\n const platform = process.platform;\n const toolName =\n platform === \"darwin\"\n ? \"imagesnap\"\n : platform === \"linux\"\n ? \"fswebcam\"\n : \"ffmpeg\";\n logger.warn(\n `[VisionService] Camera capture tool '${toolName}' not found. Install it to enable camera functionality.`,\n );\n logger.warn(\"[VisionService] For macOS: brew install imagesnap\");\n logger.warn(\"[VisionService] For Linux: sudo apt-get install fswebcam\");\n logger.warn(\n \"[VisionService] For Windows: Install ffmpeg and add to PATH\",\n );\n return;\n }\n\n // Find and connect to camera\n const camera = await this.findCamera();\n if (camera) {\n this.camera = camera;\n logger.info(`[VisionService] Connected to camera: ${camera.name}`);\n } else {\n logger.warn(\"[VisionService] No suitable camera found\");\n }\n }\n\n private async initializeAudioCapture(): Promise<void> {\n const getSettingString = (key: string): string | undefined => {\n const value = this.runtime.getSetting(key);\n return value === true || value === false\n ? String(value)\n : typeof value === \"string\"\n ? value\n : typeof value === \"number\"\n ? String(value)\n : undefined;\n };\n const enableMicrophone = getSettingString(\"ENABLE_MICROPHONE\") === \"true\";\n const useStreamingAudio =\n getSettingString(\"USE_STREAMING_AUDIO\") === \"true\";\n\n if (!enableMicrophone) {\n logger.info(\"[VisionService] Microphone capture disabled\");\n return;\n }\n\n try {\n if (useStreamingAudio) {\n // Use new streaming audio with VAD\n const getSettingNumber = (\n key: string,\n defaultValue: number,\n ): number => {\n const value = this.runtime.getSetting(key);\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\") {\n const parsed = Number(value);\n return Number.isNaN(parsed) ? defaultValue : parsed;\n }\n return defaultValue;\n };\n const streamingConfig: StreamingAudioConfig = {\n enabled: true,\n sampleRate: 16000,\n channels: 1,\n vadThreshold: getSettingNumber(\"VAD_THRESHOLD\", 0.01),\n silenceTimeout: getSettingNumber(\"SILENCE_TIMEOUT\", 1500),\n responseDelay: getSettingNumber(\"RESPONSE_DELAY\", 3000),\n };\n\n this.streamingAudioCapture = new StreamingAudioCaptureService(\n this.runtime,\n streamingConfig,\n );\n\n // Set up event listeners\n this.streamingAudioCapture.on(\"speechStart\", () => {\n logger.info(\"[VisionService] User started speaking\");\n });\n\n this.streamingAudioCapture.on(\"speechEnd\", () => {\n logger.info(\"[VisionService] User stopped speaking\");\n });\n\n this.streamingAudioCapture.on(\n \"transcription\",\n (data: { text: string; isFinal: boolean }) => {\n logger.info(\n `[VisionService] Transcription (${data.isFinal ? \"final\" : \"partial\"}): ${data.text}`,\n );\n },\n );\n\n this.streamingAudioCapture.on(\n \"utteranceComplete\",\n async (text: string) => {\n logger.info(\"[VisionService] Processing complete utterance:\", text);\n // Store the transcription in memory for context\n await this.storeAudioTranscription(text);\n },\n );\n\n await this.streamingAudioCapture.initialize();\n logger.info(\n \"[VisionService] Streaming audio capture initialized with VAD\",\n );\n } else {\n // Use original batch audio capture\n const getSettingNumber = (\n key: string,\n defaultValue: number,\n ): number => {\n const value = this.runtime.getSetting(key);\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\") {\n const parsed = Number(value);\n return Number.isNaN(parsed) ? defaultValue : parsed;\n }\n return defaultValue;\n };\n const audioConfig: AudioConfig = {\n enabled: true,\n transcriptionInterval: getSettingNumber(\n \"TRANSCRIPTION_INTERVAL\",\n 30000,\n ),\n };\n\n this.audioCapture = new AudioCaptureService(this.runtime, audioConfig);\n await this.audioCapture.initialize();\n logger.info(\"[VisionService] Batch audio capture initialized\");\n }\n } catch (error) {\n logger.error(\n \"[VisionService] Failed to initialize audio capture:\",\n error,\n );\n // Continue without audio\n }\n }\n\n private async storeAudioTranscription(text: string): Promise<void> {\n try {\n // Store transcription in the current scene description\n if (this.lastSceneDescription) {\n this.lastSceneDescription.audioTranscription = text;\n }\n\n // You could also create a memory here if needed\n logger.debug(\n \"[VisionService] Stored audio transcription in scene context\",\n );\n } catch (error) {\n logger.error(\n \"[VisionService] Failed to store audio transcription:\",\n error,\n );\n }\n }\n\n private startProcessing(): void {\n // Start camera processing if enabled\n if (\n (this.visionConfig.visionMode === VisionMode.CAMERA ||\n this.visionConfig.visionMode === VisionMode.BOTH) &&\n this.camera\n ) {\n this.startFrameProcessing();\n }\n\n // Start screen processing if enabled\n if (\n this.visionConfig.visionMode === VisionMode.SCREEN ||\n this.visionConfig.visionMode === VisionMode.BOTH\n ) {\n this.startScreenProcessing();\n }\n }\n\n private startFrameProcessing(): void {\n if (this.frameProcessingInterval) {\n return;\n }\n\n this.frameProcessingInterval = setInterval(async () => {\n if (!this.isProcessing && this.camera) {\n this.isProcessing = true;\n try {\n await this.captureAndProcessFrame();\n } catch (error) {\n logger.error(\"[VisionService] Frame processing error:\", error);\n }\n this.isProcessing = false;\n }\n }, this.visionConfig.updateInterval || 100);\n\n logger.debug(\"[VisionService] Started frame processing loop\");\n }\n\n private async captureAndProcessFrame(): Promise<void> {\n if (!this.camera) {\n return;\n }\n\n try {\n // Capture frame from camera\n const frameData = await this.camera.capture();\n\n // Skip if no data\n if (!frameData || frameData.length === 0) {\n logger.debug(\"[VisionService] Camera returned empty frame, skipping\");\n return;\n }\n\n // Convert to standardized format\n const frame = await this.processFrameData(frameData);\n\n // Validate frame before processing\n if (!frame || frame.width === 0 || frame.height === 0) {\n logger.warn(\"[VisionService] Invalid frame dimensions, skipping\");\n return;\n }\n\n // Check if scene has changed significantly\n const changePercentage = this.lastFrame\n ? await this.calculatePixelChange(this.lastFrame, frame)\n : 100;\n\n // Update scene description if change is significant or enough time has passed\n // Always call updateSceneDescription - it will decide what to update based on thresholds\n await this.updateSceneDescription(frame, changePercentage);\n\n this.lastFrame = frame;\n } catch (error) {\n logger.error(\"[VisionService] Error capturing frame:\", error);\n }\n }\n\n private async processFrameData(data: Buffer): Promise<VisionFrame> {\n // Validate input data\n if (!data || data.length === 0) {\n throw new Error(\"Empty frame data received from camera\");\n }\n\n // Use sharp to ensure consistent format\n const image = sharp(data);\n const metadata = await image.metadata();\n\n // Validate metadata\n if (\n !metadata.width ||\n !metadata.height ||\n metadata.width === 0 ||\n metadata.height === 0\n ) {\n throw new Error(\n `Invalid image dimensions: ${metadata.width}x${metadata.height}`,\n );\n }\n\n const rgbaBuffer = await image.ensureAlpha().raw().toBuffer();\n\n return {\n timestamp: Date.now(),\n width: metadata.width,\n height: metadata.height,\n data: rgbaBuffer,\n format: \"rgba\",\n };\n }\n\n private async calculatePixelChange(\n frame1: VisionFrame,\n frame2: VisionFrame,\n ): Promise<number> {\n if (frame1.width !== frame2.width || frame1.height !== frame2.height) {\n return 100; // Different dimensions = complete change\n }\n\n const pixels1 = frame1.data;\n const pixels2 = frame2.data;\n let changedPixels = 0;\n const totalPixels = frame1.width * frame1.height;\n const threshold = 30; // RGB difference threshold\n\n for (let i = 0; i < pixels1.length; i += 4) {\n const r1 = pixels1[i];\n const g1 = pixels1[i + 1];\n const b1 = pixels1[i + 2];\n const r2 = pixels2[i];\n const g2 = pixels2[i + 1];\n const b2 = pixels2[i + 2];\n\n const diff = Math.abs(r1 - r2) + Math.abs(g1 - g2) + Math.abs(b1 - b2);\n if (diff > threshold) {\n changedPixels++;\n }\n }\n\n return (changedPixels / totalPixels) * 100;\n }\n\n private async updateSceneDescription(\n frame: VisionFrame,\n changePercentage: number,\n ): Promise<void> {\n try {\n const currentTime = Date.now();\n\n // Test-input override: when ELIZA_VISION_TEST_INPUT=image, replace the\n // captured frame with the fixture PNG so the rest of the pipeline runs\n // unmodified. Returns null when no override is active.\n const testImage = getTestImage();\n\n // Convert frame to base64 for VLM\n const jpegBuffer = testImage\n ? await sharp(testImage).jpeg().toBuffer()\n : await sharp(frame.data, {\n raw: {\n width: frame.width,\n height: frame.height,\n channels: 4,\n },\n })\n .jpeg()\n .toBuffer();\n\n const base64Image = jpegBuffer.toString(\"base64\");\n const imageUrl = `data:image/jpeg;base64,${base64Image}`;\n\n // Determine if we should update VLM description\n const timeSinceVlmUpdate = currentTime - this.lastVlmUpdateTime;\n const vlmUpdateInterval = this.visionConfig.vlmUpdateInterval ?? 10000;\n const vlmChangeThreshold = this.visionConfig.vlmChangeThreshold ?? 50;\n const shouldUpdateVlm =\n timeSinceVlmUpdate >= vlmUpdateInterval || // Time threshold\n changePercentage >= vlmChangeThreshold; // Change threshold\n\n let description = this.lastTfDescription;\n\n if (shouldUpdateVlm) {\n // Use VLM to describe the scene\n description = await this.describeSceneWithVLM(imageUrl);\n this.lastVlmUpdateTime = currentTime;\n this.lastTfDescription = description;\n logger.debug(\n `[VisionService] VLM updated: ${timeSinceVlmUpdate}ms since last update, ${changePercentage.toFixed(1)}% change`,\n );\n }\n\n // Determine if we should update TensorFlow detections\n const timeSinceTfUpdate = currentTime - this.lastTfUpdateTime;\n const tfUpdateInterval = this.visionConfig.tfUpdateInterval ?? 1000;\n const tfChangeThreshold = this.visionConfig.tfChangeThreshold ?? 10;\n const shouldUpdateTf =\n timeSinceTfUpdate >= tfUpdateInterval || // Time threshold\n changePercentage >= tfChangeThreshold; // Change threshold\n\n let detectedObjects: DetectedObject[] = [];\n let people: PersonInfo[] = [];\n\n if (\n shouldUpdateTf &&\n (this.visionConfig.enableObjectDetection ||\n this.visionConfig.enablePoseDetection)\n ) {\n this.lastTfUpdateTime = currentTime;\n logger.debug(\n `[VisionService] TF updating: ${timeSinceTfUpdate}ms since last update, ${changePercentage.toFixed(1)}% change`,\n );\n\n // Use advanced computer vision if enabled\n if (this.visionConfig.enableObjectDetection) {\n if (this.visionModels.hasObjectDetection()) {\n detectedObjects = await this.visionModels.detectObjects(\n frame.data,\n frame.width,\n frame.height,\n );\n logger.debug(\n `[VisionService] VisionModels detected ${detectedObjects.length} objects`,\n );\n }\n }\n\n if (this.visionConfig.enablePoseDetection) {\n if (this.visionModels.hasPoseDetection()) {\n const poses = await this.visionModels.detectPoses(\n frame.data,\n frame.width,\n frame.height,\n );\n people = poses;\n logger.debug(\n `[VisionService] VisionModels detected ${people.length} people with poses`,\n );\n }\n }\n\n // If no people detected via pose but objects detected, check for person objects\n if (people.length === 0 && detectedObjects.length > 0) {\n const personObjects = detectedObjects.filter(\n (obj) => obj.type === \"person\",\n );\n people = personObjects.map((obj) => ({\n id: `person-${obj.id}`,\n pose: \"unknown\" as const,\n facing: \"unknown\" as const,\n confidence: obj.confidence,\n boundingBox: obj.boundingBox,\n }));\n }\n } else if (!shouldUpdateTf && this.lastSceneDescription) {\n // Reuse last detection results if not updating\n detectedObjects = this.lastSceneDescription.objects;\n people = this.lastSceneDescription.people;\n } else {\n // Fall back to motion-based detection\n detectedObjects = await this.detectMotionObjects(frame);\n people = await this.detectPeopleFromMotion(frame, detectedObjects);\n }\n\n // Face recognition and entity tracking\n const faceProfiles = new Map<string, string>();\n const getSettingString = (key: string): string | undefined => {\n const value = this.runtime.getSetting(key);\n return value === true || value === false\n ? String(value)\n : typeof value === \"string\"\n ? value\n : typeof value === \"number\"\n ? String(value)\n : undefined;\n };\n const enableFaceRecognition =\n getSettingString(\"ENABLE_FACE_RECOGNITION\") === \"true\";\n\n if (\n enableFaceRecognition &&\n people.length > 0 &&\n frame.width > 0 &&\n frame.height > 0\n ) {\n try {\n // Validate frame data\n if (frame.data.length === 0) {\n logger.warn(\n \"[VisionService] Invalid frame data for face recognition\",\n );\n return;\n }\n\n // Detect faces in the frame\n const faces = await this.faceRecognition.detectFaces(\n frame.data,\n frame.width,\n frame.height,\n );\n\n // Match faces to people based on bounding box overlap\n for (const face of faces) {\n const faceBox = face.detection.box;\n\n // Find the person this face belongs to\n for (const person of people) {\n const overlap = this.calculateBoxOverlap(person.boundingBox, {\n x: Math.round(faceBox.x),\n y: Math.round(faceBox.y),\n width: Math.round(faceBox.width),\n height: Math.round(faceBox.height),\n });\n\n if (overlap > 0.5) {\n // 50% overlap threshold\n // Recognize or register the face\n const match = await this.faceRecognition.recognizeFace(\n face.descriptor,\n );\n let profileId: string;\n\n if (match) {\n profileId = match.profileId;\n logger.debug(\n `[VisionService] Recognized face: ${profileId} (distance: ${match.distance})`,\n );\n } else {\n // Register new face\n profileId = await this.faceRecognition.addOrUpdateFace(\n face.descriptor,\n {\n attributes: {\n age: face.ageGender?.age.toString(),\n gender: face.ageGender?.gender,\n emotion: face.expressions\n ? this.getDominantExpression(face.expressions)\n : undefined,\n },\n },\n );\n logger.info(\n `[VisionService] New face registered: ${profileId}`,\n );\n }\n\n faceProfiles.set(person.id, profileId);\n break;\n }\n }\n }\n } catch (faceError) {\n logger.error(\"[VisionService] Face recognition error:\", faceError);\n }\n }\n\n // Update entity tracker\n const _trackedEntities = await this.entityTracker.updateEntities(\n detectedObjects,\n people,\n faceProfiles,\n this.runtime,\n );\n\n // Create scene description\n this.lastSceneDescription = {\n timestamp: frame.timestamp,\n description,\n objects: detectedObjects,\n people,\n sceneChanged: shouldUpdateVlm || shouldUpdateTf,\n changePercentage,\n };\n\n // Enhanced logging\n if (shouldUpdateVlm || shouldUpdateTf) {\n logger.info(\"[VisionService] Scene Analysis Complete:\");\n logger.info(` VLM Description: ${description.substring(0, 100)}...`);\n logger.info(` Change: ${changePercentage.toFixed(1)}%`);\n logger.info(\n ` Updates: ${shouldUpdateVlm ? \"VLM\" : \"\"}${shouldUpdateVlm && shouldUpdateTf ? \" + \" : \"\"}${shouldUpdateTf ? \"TF\" : \"\"}`,\n );\n logger.info(\n ` Detection Mode: ${this.visionConfig.enableObjectDetection ? \"Advanced CV\" : \"Motion-based\"}`,\n );\n\n if (detectedObjects.length > 0) {\n logger.info(` Objects: ${detectedObjects.length} detected`);\n\n // Group objects by type for summary\n const objectSummary = detectedObjects.reduce(\n (acc, obj) => {\n acc[obj.type] = (acc[obj.type] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>,\n );\n\n for (const [type, count] of Object.entries(objectSummary)) {\n logger.info(` - ${count} ${type}(s)`);\n }\n }\n\n if (people.length > 0) {\n logger.info(` People: ${people.length} detected`);\n for (const person of people) {\n logger.info(\n ` - Person: ${person.pose} pose, facing ${person.facing}, confidence: ${person.confidence.toFixed(2)}`,\n );\n }\n }\n }\n } catch (error) {\n logger.error(\n \"[VisionService] Failed to update scene description:\",\n error,\n );\n }\n }\n\n private async describeSceneWithVLM(imageUrl: string): Promise<string> {\n return withStandaloneTrajectory(\n this.runtime,\n {\n source: \"plugin-vision:scene-description\",\n metadata: { modelType: ModelType.IMAGE_DESCRIPTION },\n },\n () => this.describeSceneWithVLMInTrajectory(imageUrl),\n );\n }\n\n private async describeSceneWithVLMInTrajectory(\n imageUrl: string,\n ): Promise<string> {\n try {\n // Convert base64 image URL to buffer for Florence-2\n if (imageUrl.startsWith(\"data:image/\")) {\n const base64Data = imageUrl.split(\",\")[1];\n const imageBuffer = Buffer.from(base64Data, \"base64\");\n\n // Use Florence-2 for all image descriptions\n if (this.florence2.isInitialized()) {\n try {\n const result = await recordLlmCall(\n this.runtime,\n {\n model: \"florence2-local\",\n systemPrompt: \"\",\n userPrompt: JSON.stringify(\n {\n task: \"describe_visual_scene\",\n image: {\n source: \"camera_frame\",\n mimeType: \"image/jpeg\",\n bytes: imageBuffer.byteLength,\n },\n },\n null,\n 2,\n ),\n temperature: 0,\n maxTokens: 0,\n purpose: \"background\",\n actionType: \"florence2.analyzeImage\",\n },\n () => this.florence2.analyzeImage(imageBuffer),\n );\n if (result.caption) {\n logger.debug(\n \"[VisionService] Florence-2 description:\",\n result.caption,\n );\n return result.caption;\n }\n } catch (florenceError) {\n logger.warn(\n \"[VisionService] Florence-2 analysis failed, falling back:\",\n florenceError,\n );\n }\n }\n }\n\n // Fallback to runtime model if Florence-2 is not available\n try {\n const result = await this.runtime.useModel(\n ModelType.IMAGE_DESCRIPTION,\n {\n imageUrl,\n prompt: SCENE_DESCRIPTION_PROMPT,\n },\n );\n\n if (result && typeof result === \"object\" && \"description\" in result) {\n const description = (result as { description: string }).description;\n // Check if we got the unhelpful default response\n if (\n !description.includes(\"I'm unable to analyze images\") &&\n !description.includes(\"I can't analyze images\")\n ) {\n return description;\n }\n } else if (typeof result === \"string\") {\n const stringResult = result as string;\n if (\n stringResult.length > 0 &&\n !stringResult.includes(\"I'm unable to analyze images\") &&\n !stringResult.includes(\"I can't analyze images\")\n ) {\n return stringResult;\n }\n }\n } catch (modelError) {\n logger.warn(\n \"[VisionService] Runtime IMAGE_DESCRIPTION model failed:\",\n modelError,\n );\n }\n\n // If we got the unhelpful response or an error, provide a basic description based on detected objects\n if (this.lastSceneDescription) {\n const { objects, people } = this.lastSceneDescription;\n let description = \"Scene contains\";\n\n if (people.length > 0) {\n description += ` ${people.length} person${people.length > 1 ? \"s\" : \"\"}`;\n const poses = people\n .map((p) => p.pose)\n .filter((p) => p !== \"unknown\");\n if (poses.length > 0) {\n description += ` (${poses.join(\", \")})`;\n }\n }\n\n if (objects.length > 0 && people.length > 0) {\n description += \" and\";\n }\n\n if (objects.length > 0) {\n const objectTypes = [...new Set(objects.map((o) => o.type))];\n description += ` ${objectTypes.join(\", \")}`;\n }\n\n if (people.length === 0 && objects.length === 0) {\n description = \"Scene appears to be empty or static\";\n }\n\n return description;\n }\n\n // Final fallback\n return \"Visual scene captured\";\n } catch (error) {\n logger.error(\"[VisionService] VLM description failed:\", error);\n return \"Unable to describe scene\";\n }\n }\n\n private async detectMotionObjects(\n frame: VisionFrame,\n ): Promise<DetectedObject[]> {\n if (!this.lastFrame) {\n return [];\n }\n\n const objects: DetectedObject[] = [];\n const blockSize = 64; // Larger blocks for less noise\n const motionThreshold = 50; // Higher threshold for more significant changes\n\n // Divide frame into blocks and detect motion regions\n for (let y = 0; y < frame.height - blockSize; y += blockSize / 2) {\n // Overlap blocks\n for (let x = 0; x < frame.width - blockSize; x += blockSize / 2) {\n let blockMotion = 0;\n let pixelCount = 0;\n\n // Check motion in this block\n for (let by = 0; by < blockSize; by += 2) {\n // Sample every other pixel for speed\n for (let bx = 0; bx < blockSize; bx += 2) {\n const px = x + bx;\n const py = y + by;\n const idx = (py * frame.width + px) * 4;\n\n if (idx < frame.data.length && idx < this.lastFrame.data.length) {\n const r1 = frame.data[idx];\n const g1 = frame.data[idx + 1];\n const b1 = frame.data[idx + 2];\n const r2 = this.lastFrame.data[idx];\n const g2 = this.lastFrame.data[idx + 1];\n const b2 = this.lastFrame.data[idx + 2];\n\n const diff =\n Math.abs(r1 - r2) + Math.abs(g1 - g2) + Math.abs(b1 - b2);\n if (diff > motionThreshold) {\n blockMotion++;\n }\n pixelCount++;\n }\n }\n }\n\n // If significant motion in block, consider it an object\n const motionPercentage = (blockMotion / pixelCount) * 100;\n if (motionPercentage > 30) {\n // 30% of sampled pixels show motion\n objects.push({\n id: `motion-${x}-${y}-${frame.timestamp}`,\n type: \"motion-object\",\n confidence: Math.min(motionPercentage / 100, 1),\n boundingBox: {\n x,\n y,\n width: blockSize,\n height: blockSize,\n },\n });\n }\n }\n }\n\n // Merge adjacent motion blocks into larger objects\n const merged = this.mergeAdjacentObjects(objects);\n\n // Filter out very small objects (likely noise)\n const filtered = merged.filter((obj) => {\n const area = obj.boundingBox.width * obj.boundingBox.height;\n return area > 2000; // Minimum area threshold\n });\n\n return filtered;\n }\n\n private mergeAdjacentObjects(objects: DetectedObject[]): DetectedObject[] {\n if (objects.length === 0) {\n return [];\n }\n\n const merged: DetectedObject[] = [];\n const used = new Set<number>();\n const mergeDistance = 80; // Distance to consider objects adjacent\n\n for (let i = 0; i < objects.length; i++) {\n if (used.has(i)) {\n continue;\n }\n\n const current = objects[i];\n const cluster: DetectedObject[] = [current];\n used.add(i);\n\n // Find all adjacent objects\n let foundNew = true;\n while (foundNew) {\n foundNew = false;\n for (let j = 0; j < objects.length; j++) {\n if (used.has(j)) {\n continue;\n }\n\n const other = objects[j];\n\n // Check if adjacent to any object in cluster\n for (const clusterObj of cluster) {\n const isAdjacent =\n Math.abs(clusterObj.boundingBox.x - other.boundingBox.x) <=\n mergeDistance &&\n Math.abs(clusterObj.boundingBox.y - other.boundingBox.y) <=\n mergeDistance;\n\n if (isAdjacent) {\n cluster.push(other);\n used.add(j);\n foundNew = true;\n break;\n }\n }\n }\n }\n\n // Merge cluster into single object\n if (cluster.length > 0) {\n const minX = Math.min(...cluster.map((o) => o.boundingBox.x));\n const minY = Math.min(...cluster.map((o) => o.boundingBox.y));\n const maxX = Math.max(\n ...cluster.map((o) => o.boundingBox.x + o.boundingBox.width),\n );\n const maxY = Math.max(\n ...cluster.map((o) => o.boundingBox.y + o.boundingBox.height),\n );\n const avgConfidence =\n cluster.reduce((sum, o) => sum + o.confidence, 0) / cluster.length;\n\n merged.push({\n id: `merged-${minX}-${minY}-${Date.now()}`,\n type: this.classifyObjectBySize(maxX - minX, maxY - minY),\n confidence: avgConfidence,\n boundingBox: {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY,\n },\n });\n }\n }\n\n return merged;\n }\n\n private classifyObjectBySize(width: number, height: number): string {\n const area = width * height;\n const aspectRatio = width / height;\n\n // Improved classification heuristics\n if (area > 30000 && aspectRatio > 0.4 && aspectRatio < 0.8) {\n return \"person-candidate\";\n } else if (area > 20000) {\n return \"large-object\";\n } else if (area > 8000) {\n return \"medium-object\";\n } else {\n return \"small-object\";\n }\n }\n\n private async detectPeopleFromMotion(\n frame: VisionFrame,\n objects: DetectedObject[],\n ): Promise<PersonInfo[]> {\n const people: PersonInfo[] = [];\n const personCandidates = objects.filter(\n (o) => o.type === \"person-candidate\",\n );\n\n for (let i = 0; i < personCandidates.length; i++) {\n const candidate = personCandidates[i];\n const box = candidate.boundingBox;\n\n // Simple heuristic: if height > width * 1.5, likely standing\n // if width > height, likely sitting/lying\n const aspectRatio = box.width / box.height;\n let pose: \"standing\" | \"sitting\" | \"lying\" | \"unknown\" = \"unknown\";\n\n if (aspectRatio < 0.6) {\n pose = \"standing\";\n } else if (aspectRatio > 1.2) {\n pose = \"lying\";\n } else {\n pose = \"sitting\";\n }\n\n // Estimate facing based on motion direction (simplified)\n let facing: \"camera\" | \"away\" | \"left\" | \"right\" | \"unknown\" = \"unknown\";\n if (this.lastFrame) {\n // In Phase 1, we'll just use 'unknown' or random assignment\n // Phase 2 will implement proper pose detection\n facing = \"camera\"; // Default assumption\n }\n\n people.push({\n id: `person-${i}-${frame.timestamp}`,\n confidence: candidate.confidence,\n pose,\n facing,\n boundingBox: box,\n });\n }\n\n return people;\n }\n\n private startScreenProcessing(): void {\n if (this.screenProcessingInterval) {\n return;\n }\n\n this.screenProcessingInterval = setInterval(async () => {\n if (!this.isProcessingScreen) {\n this.isProcessingScreen = true;\n try {\n await this.captureAndProcessScreen();\n } catch (error) {\n logger.error(\"[VisionService] Screen processing error:\", error);\n }\n this.isProcessingScreen = false;\n }\n }, this.visionConfig.screenCaptureInterval || 2000);\n\n logger.debug(\"[VisionService] Started screen processing loop\");\n }\n\n private async captureAndProcessScreen(): Promise<void> {\n try {\n // Capture screen\n const capture = await this.screenCapture.captureScreen();\n this.lastScreenCapture = capture;\n\n // Process active tile\n const activeTile = this.screenCapture.getActiveTile();\n if (activeTile?.data) {\n const tileAnalysis = await this.analyzeTile(activeTile);\n activeTile.analysis = tileAnalysis;\n }\n\n // Update enhanced scene description\n await this.updateEnhancedSceneDescription();\n } catch (error) {\n logger.error(\"[VisionService] Error capturing screen:\", error);\n }\n }\n\n private async analyzeTile(tile: ScreenTile): Promise<TileAnalysis> {\n const analysis: TileAnalysis = {\n timestamp: Date.now(),\n };\n\n try {\n // Run Florence-2 analysis if enabled\n if (this.visionConfig.florence2Enabled && tile.data) {\n analysis.florence2 = await this.florence2.analyzeTile(tile);\n analysis.summary = analysis.florence2.caption;\n }\n\n // Run OCR if enabled\n if (this.visionConfig.ocrEnabled && tile.data) {\n analysis.ocr = await this.ocrService.extractFromTile(tile);\n analysis.text = analysis.ocr.fullText;\n }\n\n // Extract objects from Florence-2 results\n if (analysis.florence2?.objects) {\n analysis.objects = analysis.florence2.objects.map((obj) => ({\n id: `screen-obj-${Date.now()}-${Math.random()}`,\n type: obj.label,\n confidence: obj.confidence,\n boundingBox: obj.bbox,\n }));\n }\n } catch (error) {\n logger.error(\"[VisionService] Error analyzing tile:\", error);\n }\n\n return analysis;\n }\n\n private async updateEnhancedSceneDescription(): Promise<void> {\n if (!this.lastScreenCapture) {\n return;\n }\n\n const enhancedScene: EnhancedSceneDescription = {\n ...(this.lastSceneDescription || {\n timestamp: Date.now(),\n description: \"\",\n objects: [],\n people: [],\n sceneChanged: false,\n changePercentage: 0,\n }),\n screenCapture: this.lastScreenCapture,\n screenAnalysis: {\n fullScreenOCR: \"\",\n activeTile: this.screenCapture.getActiveTile()?.analysis,\n gridSummary: \"\",\n focusedApp: \"\",\n uiElements: [],\n },\n };\n\n // Aggregate OCR from all processed tiles\n const processedTiles = this.lastScreenCapture.tiles.filter(\n (t) => t.analysis?.ocr,\n );\n if (processedTiles.length > 0 && enhancedScene.screenAnalysis) {\n enhancedScene.screenAnalysis.fullScreenOCR = processedTiles\n .map((t) => t.analysis?.ocr?.fullText)\n .join(\"\\n\");\n }\n\n // Generate grid summary\n if (\n this.lastScreenCapture.tiles.length > 0 &&\n enhancedScene.screenAnalysis\n ) {\n const tilesWithContent = this.lastScreenCapture.tiles.filter(\n (t) => t.analysis,\n );\n enhancedScene.screenAnalysis.gridSummary = `Screen divided into ${this.lastScreenCapture.tiles.length} tiles, ${tilesWithContent.length} analyzed`;\n }\n\n // Detect focused application (heuristic based on UI elements)\n if (enhancedScene.screenAnalysis?.activeTile?.florence2?.objects) {\n const windows =\n enhancedScene.screenAnalysis.activeTile.florence2.objects.filter(\n (obj) => obj.label === \"window\",\n );\n if (windows.length > 0 && enhancedScene.screenAnalysis) {\n enhancedScene.screenAnalysis.focusedApp = \"Desktop Application\";\n }\n }\n\n this.lastEnhancedScene = enhancedScene;\n }\n\n // Public API methods\n\n public async getCurrentFrame(): Promise<VisionFrame | null> {\n return this.lastFrame;\n }\n\n public async getSceneDescription(): Promise<SceneDescription | null> {\n return this.lastSceneDescription;\n }\n\n public async getEnhancedSceneDescription(): Promise<EnhancedSceneDescription | null> {\n // If worker manager is available, use its high-FPS data\n if (this.workerManager) {\n return this.workerManager.getLatestEnhancedScene();\n }\n\n // Otherwise fall back to standard processing\n return this.lastEnhancedScene || this.lastSceneDescription;\n }\n\n public async getScreenCapture(): Promise<ScreenCapture | null> {\n return this.lastScreenCapture;\n }\n\n public getVisionMode(): VisionMode {\n return this.visionConfig.visionMode || VisionMode.CAMERA;\n }\n\n public async setVisionMode(mode: VisionMode): Promise<void> {\n logger.info(\n `[VisionService] Changing vision mode from ${this.visionConfig.visionMode} to ${mode}`,\n );\n\n // Stop current processing\n this.stopProcessing();\n\n // Update configuration\n this.visionConfig.visionMode = mode;\n\n // Reinitialize based on new mode\n if (mode === VisionMode.OFF) {\n logger.info(\"[VisionService] Vision disabled\");\n return;\n }\n\n // Initialize components for new mode\n if (\n (mode === VisionMode.CAMERA || mode === VisionMode.BOTH) &&\n !this.camera\n ) {\n await this.initializeCameraVision();\n }\n\n if (\n (mode === VisionMode.SCREEN || mode === VisionMode.BOTH) &&\n (!this.florence2.isInitialized() || !this.ocrService.isInitialized())\n ) {\n await this.initializeScreenVision();\n }\n\n // Start processing for new mode\n this.startProcessing();\n }\n\n private stopProcessing(): void {\n if (this.frameProcessingInterval) {\n clearInterval(this.frameProcessingInterval);\n this.frameProcessingInterval = null;\n }\n\n if (this.screenProcessingInterval) {\n clearInterval(this.screenProcessingInterval);\n this.screenProcessingInterval = null;\n }\n }\n\n public getCameraInfo(): CameraInfo | null {\n if (!this.camera) {\n return null;\n }\n\n return {\n id: this.camera.id,\n name: this.camera.name,\n connected: true,\n };\n }\n\n public isActive(): boolean {\n return this.camera !== null && this.frameProcessingInterval !== null;\n }\n\n // Helper methods for face recognition\n private calculateBoxOverlap(box1: BoundingBox, box2: BoundingBox): number {\n const x1 = Math.max(box1.x, box2.x);\n const y1 = Math.max(box1.y, box2.y);\n const x2 = Math.min(box1.x + box1.width, box2.x + box2.width);\n const y2 = Math.min(box1.y + box1.height, box2.y + box2.height);\n\n if (x2 < x1 || y2 < y1) {\n return 0;\n }\n\n const intersection = (x2 - x1) * (y2 - y1);\n const area1 = box1.width * box1.height;\n const area2 = box2.width * box2.height;\n const union = area1 + area2 - intersection;\n\n return intersection / union;\n }\n\n private getDominantExpression(expressions: {\n neutral: number;\n happy: number;\n sad: number;\n angry: number;\n fearful: number;\n disgusted: number;\n surprised: number;\n }): string {\n let maxValue = 0;\n let dominantExpression = \"neutral\";\n\n const expressionEntries: [string, number][] = [\n [\"neutral\", expressions.neutral],\n [\"happy\", expressions.happy],\n [\"sad\", expressions.sad],\n [\"angry\", expressions.angry],\n [\"fearful\", expressions.fearful],\n [\"disgusted\", expressions.disgusted],\n [\"surprised\", expressions.surprised],\n ];\n\n for (const [expression, value] of expressionEntries) {\n if (value > maxValue) {\n maxValue = value;\n dominantExpression = expression;\n }\n }\n\n return dominantExpression;\n }\n\n // Public methods for entity tracking\n public getEntityTracker(): EntityTracker {\n return this.entityTracker;\n }\n\n public getFaceRecognition(): FaceRecognition {\n return this.faceRecognition;\n }\n\n async stop(): Promise<void> {\n logger.info(\"[VisionService] Stopping vision service...\");\n\n this.stopProcessing();\n\n if (this.audioCapture) {\n await this.audioCapture.stop();\n this.audioCapture = null;\n }\n\n if (this.streamingAudioCapture) {\n await this.streamingAudioCapture.stop();\n this.streamingAudioCapture = null;\n }\n\n if (this.visionModels) {\n await this.visionModels.dispose();\n }\n\n if (this.workerManager) {\n await this.workerManager.stop();\n this.workerManager = null;\n }\n\n this.camera = null;\n this.lastFrame = null;\n this.lastSceneDescription = null;\n this.lastScreenCapture = null;\n this.lastEnhancedScene = null;\n this.isProcessing = false;\n this.isProcessingScreen = false;\n\n // Dispose of models\n await this.florence2.dispose();\n await this.ocrService.dispose();\n\n logger.info(\"[VisionService] Stopped.\");\n }\n\n private async findCamera(): Promise<CameraDevice | null> {\n try {\n // Get list of available cameras\n const cameras = await this.listCameras();\n\n if (cameras.length === 0) {\n logger.warn(\"[VisionService] No cameras detected\");\n return null;\n }\n\n // If camera name is specified, try to find it\n if (this.visionConfig.cameraName) {\n const searchName = this.visionConfig.cameraName.toLowerCase();\n const matchedCamera = cameras.find((cam) =>\n cam.name.toLowerCase().includes(searchName),\n );\n\n if (matchedCamera) {\n return this.createCameraDevice(matchedCamera);\n }\n\n logger.warn(\n `[VisionService] Camera \"${this.visionConfig.cameraName}\" not found, using default`,\n );\n }\n\n // Use first available camera\n return this.createCameraDevice(cameras[0]);\n } catch (error) {\n logger.error(\"[VisionService] Error finding camera:\", error);\n return null;\n }\n }\n\n private async listCameras(): Promise<CameraInfo[]> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // macOS: Use system_profiler\n const { stdout } = await execAsync(\n \"system_profiler SPCameraDataType -json\",\n );\n const data = JSON.parse(stdout);\n const cameras: CameraInfo[] = [];\n\n if (data.SPCameraDataType && Array.isArray(data.SPCameraDataType)) {\n for (const camera of data.SPCameraDataType) {\n cameras.push({\n id: camera.unique_id || camera._name,\n name: camera._name,\n connected: true,\n });\n }\n }\n\n return cameras;\n } else if (platform === \"linux\") {\n // Linux: Use v4l2\n const { stdout } = await execAsync(\"v4l2-ctl --list-devices\");\n const cameras: CameraInfo[] = [];\n const lines = stdout.split(\"\\n\");\n\n let currentName = \"\";\n for (const line of lines) {\n if (line && !line.startsWith(\"\\t\")) {\n currentName = line.replace(\":\", \"\").trim();\n } else if (line.trim().startsWith(\"/dev/video\")) {\n const devicePath = line.trim();\n const id = devicePath.replace(\"/dev/video\", \"\");\n cameras.push({\n id,\n name: currentName,\n connected: true,\n });\n }\n }\n\n return cameras;\n } else if (platform === \"win32\") {\n // Windows: Use PowerShell\n const { stdout } = await execAsync(\n 'powershell -Command \"Get-PnpDevice -Class Camera | Select-Object FriendlyName, InstanceId | ConvertTo-Json\"',\n );\n const devices = JSON.parse(stdout);\n const cameras: CameraInfo[] = [];\n\n if (Array.isArray(devices)) {\n for (const device of devices) {\n cameras.push({\n id: device.InstanceId,\n name: device.FriendlyName,\n connected: true,\n });\n }\n }\n\n return cameras;\n }\n\n return [];\n } catch (error) {\n logger.error(\"[VisionService] Error listing cameras:\", error);\n return [];\n }\n }\n\n private createCameraDevice(info: CameraInfo): CameraDevice {\n const platform = process.platform;\n\n return {\n id: info.id,\n name: info.name,\n capture: async () => {\n const tempFile = path.join(\n process.cwd(),\n `temp_capture_${Date.now()}.jpg`,\n );\n\n try {\n if (platform === \"darwin\") {\n // macOS: Use imagesnap\n try {\n await execAsync(`imagesnap -d \"${info.name}\" \"${tempFile}\"`);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n if (errorMessage.includes(\"command not found\")) {\n throw new Error(\n \"imagesnap not installed. Run: brew install imagesnap\",\n );\n }\n throw error;\n }\n } else if (platform === \"linux\") {\n // Linux: Use fswebcam\n try {\n await execAsync(\n `fswebcam -d /dev/video${info.id} -r 1280x720 --jpeg 85 \"${tempFile}\"`,\n );\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n if (errorMessage.includes(\"command not found\")) {\n throw new Error(\n \"fswebcam not installed. Run: sudo apt-get install fswebcam\",\n );\n }\n throw error;\n }\n } else if (platform === \"win32\") {\n // Windows: Use DirectShow via ffmpeg\n try {\n await execAsync(\n `ffmpeg -f dshow -i video=\"${info.name}\" -frames:v 1 -q:v 2 \"${tempFile}\" -y`,\n );\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n if (\n errorMessage.includes(\"not recognized\") ||\n errorMessage.includes(\"not found\")\n ) {\n throw new Error(\n \"ffmpeg not installed. Download from ffmpeg.org and add to PATH\",\n );\n }\n throw error;\n }\n } else {\n throw new Error(`Unsupported platform: ${platform}`);\n }\n\n // Read the captured image\n const imageBuffer = await fs.readFile(tempFile);\n\n // Clean up temp file\n await fs.unlink(tempFile).catch(() => {});\n\n return imageBuffer;\n } catch (error) {\n // Clean up temp file on error\n await fs.unlink(tempFile).catch(() => {});\n throw error;\n }\n },\n };\n }\n\n public async captureImage(): Promise<Buffer | null> {\n if (!this.camera) {\n logger.warn(\"[VisionService] No camera available for capture\");\n return null;\n }\n\n try {\n return await this.camera.capture();\n } catch (error) {\n logger.error(\"[VisionService] Failed to capture image:\", error);\n return null;\n }\n }\n}\n",
10
+ "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 {\n type IAgentRuntime,\n logger,\n ModelType,\n withStandaloneTrajectory,\n} from \"@elizaos/core\";\n\nconst execAsync = promisify(exec);\n\nexport interface AudioConfig {\n enabled: boolean;\n transcriptionInterval: number; // milliseconds\n device?: string;\n sampleRate?: number;\n channels?: number;\n}\n\nexport class AudioCaptureService {\n private runtime: IAgentRuntime;\n private config: AudioConfig;\n private isRecording = false;\n private recordingInterval: NodeJS.Timeout | null = null;\n\n constructor(runtime: IAgentRuntime, config: AudioConfig) {\n this.runtime = runtime;\n this.config = {\n sampleRate: 16000,\n channels: 1,\n ...config,\n };\n }\n\n async initialize(): Promise<void> {\n if (!this.config.enabled) {\n logger.info(\"[AudioCapture] Audio capture disabled\");\n return;\n }\n\n try {\n logger.info(\"[AudioCapture] Initializing audio capture...\");\n\n // Check for audio recording tools\n const tool = await this.checkAudioTools();\n if (!tool.available) {\n throw new Error(`Audio recording tool not available. ${tool.message}`);\n }\n\n logger.info(`[AudioCapture] Using ${tool.tool} for audio capture`);\n logger.info(\n `[AudioCapture] Transcription interval: ${this.config.transcriptionInterval}ms`,\n );\n\n // Start recording loop if interval is set\n if (this.config.transcriptionInterval > 0) {\n this.startTranscriptionLoop();\n }\n\n logger.info(\"[AudioCapture] Audio capture initialized\");\n } catch (error) {\n logger.error(\"[AudioCapture] Failed to initialize:\", error);\n throw error;\n }\n }\n\n private async checkAudioTools(): Promise<{\n available: boolean;\n tool: string;\n message?: string;\n }> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // macOS: Use sox\n await execAsync(\"which sox\");\n return { available: true, tool: \"sox\" };\n } else if (platform === \"linux\") {\n // Linux: Use arecord (ALSA)\n await execAsync(\"which arecord\");\n return { available: true, tool: \"arecord\" };\n } else if (platform === \"win32\") {\n // Windows: Use ffmpeg\n await execAsync(\"where ffmpeg\");\n return { available: true, tool: \"ffmpeg\" };\n }\n return {\n available: false,\n tool: \"none\",\n message: \"Unsupported platform\",\n };\n } catch (_error) {\n // Tool not found\n const toolName =\n platform === \"darwin\"\n ? \"sox\"\n : platform === \"linux\"\n ? \"arecord\"\n : \"ffmpeg\";\n const installCmd =\n platform === \"darwin\"\n ? \"brew install sox\"\n : platform === \"linux\"\n ? \"sudo apt-get install alsa-utils\"\n : \"Download ffmpeg from ffmpeg.org\";\n return {\n available: false,\n tool: toolName,\n message: `Install with: ${installCmd}`,\n };\n }\n }\n\n private startTranscriptionLoop(): void {\n if (this.recordingInterval) {\n return;\n }\n\n // Start continuous recording with periodic transcription\n this.recordingInterval = setInterval(async () => {\n if (!this.isRecording) {\n await this.recordAndTranscribe();\n }\n }, this.config.transcriptionInterval);\n\n logger.info(\"[AudioCapture] Started transcription loop\");\n }\n\n async recordAndTranscribe(): Promise<string | null> {\n if (this.isRecording) {\n logger.warn(\"[AudioCapture] Already recording\");\n return null;\n }\n\n this.isRecording = true;\n const audioFile = path.join(process.cwd(), `audio_${Date.now()}.wav`);\n\n try {\n logger.debug(\"[AudioCapture] Starting audio recording...\");\n\n // Record audio for the specified duration\n await this.recordAudio(\n audioFile,\n this.config.transcriptionInterval / 1000,\n );\n\n logger.debug(\"[AudioCapture] Recording complete, transcribing...\");\n\n // Transcribe using runtime model\n const audioBuffer = await fs.readFile(audioFile);\n const transcription = await withStandaloneTrajectory(\n this.runtime,\n {\n source: \"plugin-vision:audio-transcription\",\n metadata: {\n modelType: ModelType.TRANSCRIPTION,\n audioBytes: audioBuffer.byteLength,\n },\n },\n () => this.runtime.useModel(ModelType.TRANSCRIPTION, audioBuffer),\n );\n\n // Clean up audio file\n await fs.unlink(audioFile).catch(() => {});\n\n if (\n transcription &&\n typeof transcription === \"string\" &&\n transcription.trim()\n ) {\n logger.info(`[AudioCapture] Transcribed: \"${transcription}\"`);\n\n // Create a memory of what was heard\n await this.createAudioMemory(transcription);\n\n return transcription;\n }\n\n return null;\n } catch (error) {\n logger.error(\"[AudioCapture] Recording/transcription failed:\", error);\n await fs.unlink(audioFile).catch(() => {});\n return null;\n } finally {\n this.isRecording = false;\n }\n }\n\n private async recordAudio(\n outputPath: string,\n duration: number,\n ): Promise<void> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // macOS: Use sox\n const _device = this.config.device || \"default\";\n await execAsync(\n `sox -d -r ${this.config.sampleRate} -c ${this.config.channels} -b 16 \"${outputPath}\" trim 0 ${duration}`,\n );\n } else if (platform === \"linux\") {\n // Linux: Use arecord\n const device = this.config.device || \"default\";\n await execAsync(\n `arecord -D ${device} -f S16_LE -r ${this.config.sampleRate} -c ${this.config.channels} -d ${duration} \"${outputPath}\"`,\n );\n } else if (platform === \"win32\") {\n // Windows: Use ffmpeg with DirectShow\n const device = this.config.device || \"Microphone\";\n await execAsync(\n `ffmpeg -f dshow -i audio=\"${device}\" -t ${duration} -acodec pcm_s16le -ar ${this.config.sampleRate} -ac ${this.config.channels} \"${outputPath}\" -y`,\n );\n } else {\n throw new Error(`Unsupported platform: ${platform}`);\n }\n } catch (error: unknown) {\n logger.error(\n \"[AudioCapture] Audio recording failed:\",\n error instanceof Error ? error.message : String(error),\n );\n throw error;\n }\n }\n\n private async createAudioMemory(transcription: string): Promise<void> {\n try {\n const _memory = {\n content: {\n text: `[Audio Transcription] ${transcription}`,\n type: \"audio_transcription\",\n source: \"microphone\",\n timestamp: Date.now(),\n },\n metadata: {\n isAudioTranscription: true,\n duration: this.config.transcriptionInterval,\n },\n };\n\n // Store in agent's context\n // createMemory requires runtime-specific database adapter implementation\n logger.info(\"[AudioCapture] Audio transcription stored in context\");\n } catch (error) {\n logger.error(\"[AudioCapture] Failed to create audio memory:\", error);\n }\n }\n\n async listAudioDevices(): Promise<string[]> {\n const platform = process.platform;\n const devices: string[] = [];\n\n try {\n if (platform === \"darwin\") {\n // macOS: List audio devices using system_profiler\n const { stdout } = await execAsync(\n \"system_profiler SPAudioDataType -json\",\n );\n const data = JSON.parse(stdout);\n\n if (data.SPAudioDataType) {\n for (const device of data.SPAudioDataType) {\n if (device._name?.includes(\"Input\")) {\n devices.push(device._name);\n }\n }\n }\n } else if (platform === \"linux\") {\n // Linux: List ALSA devices\n const { stdout } = await execAsync(\"arecord -l\");\n const lines = stdout.split(\"\\n\");\n\n for (const line of lines) {\n if (line.includes(\"card\")) {\n const match = line.match(/card (\\d+):.*\\[(.*?)\\]/);\n if (match) {\n devices.push(`hw:${match[1]}`);\n }\n }\n }\n } else if (platform === \"win32\") {\n // Windows: List audio devices using ffmpeg\n try {\n const { stdout } = await execAsync(\n \"ffmpeg -list_devices true -f dshow -i dummy 2>&1\",\n );\n const lines = stdout.split(\"\\n\");\n let isAudioSection = false;\n\n for (const line of lines) {\n if (line.includes(\"DirectShow audio devices\")) {\n isAudioSection = true;\n } else if (isAudioSection && line.includes('\"')) {\n const match = line.match(/\"([^\"]+)\"/);\n if (match) {\n devices.push(match[1]);\n }\n }\n }\n } catch (_error) {\n // ffmpeg returns non-zero exit code when listing devices\n // but we can still parse the output\n }\n }\n } catch (error) {\n logger.error(\"[AudioCapture] Failed to list audio devices:\", error);\n }\n\n return devices;\n }\n\n isActive(): boolean {\n return this.config.enabled && this.recordingInterval !== null;\n }\n\n async stop(): Promise<void> {\n logger.info(\"[AudioCapture] Stopping audio capture...\");\n\n if (this.recordingInterval) {\n clearInterval(this.recordingInterval);\n this.recordingInterval = null;\n }\n\n // Wait for any ongoing recording to complete\n while (this.isRecording) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n logger.info(\"[AudioCapture] Audio capture stopped\");\n }\n}\n",
11
+ "import { type ChildProcess, spawn } from \"node:child_process\";\nimport { EventEmitter } from \"node:events\";\nimport {\n type IAgentRuntime,\n logger,\n ModelType,\n withStandaloneTrajectory,\n} from \"@elizaos/core\";\n\nexport interface StreamingAudioConfig {\n enabled: boolean;\n device?: string;\n sampleRate?: number;\n channels?: number;\n vadThreshold?: number; // 0-1, energy threshold for speech detection\n silenceTimeout?: number; // ms to wait before considering speech ended\n responseDelay?: number; // ms to wait before processing (for interruption detection)\n chunkSize?: number; // bytes per chunk for streaming\n}\n\ninterface AudioChunk {\n data: Buffer;\n timestamp: number;\n energy: number;\n}\n\nexport class StreamingAudioCaptureService extends EventEmitter {\n private runtime: IAgentRuntime;\n private config: StreamingAudioConfig;\n private captureProcess: ChildProcess | null = null;\n private isCapturing = false;\n private audioBuffer: AudioChunk[] = [];\n private isSpeaking = false;\n private silenceTimer: NodeJS.Timeout | null = null;\n private transcriptionInProgress = false;\n private currentTranscription = \"\";\n private responseTimer: NodeJS.Timeout | null = null;\n\n constructor(runtime: IAgentRuntime, config: StreamingAudioConfig) {\n super();\n this.runtime = runtime;\n this.config = {\n sampleRate: 16000,\n channels: 1,\n vadThreshold: 0.01,\n silenceTimeout: 1500, // 1.5 seconds of silence to end speech\n responseDelay: 3000, // 3 seconds before response (allows for interruption)\n chunkSize: 4096,\n ...config,\n };\n }\n\n async initialize(): Promise<void> {\n if (!this.config.enabled) {\n logger.info(\"[StreamingAudio] Audio capture disabled\");\n return;\n }\n\n try {\n logger.info(\"[StreamingAudio] Initializing streaming audio capture...\");\n\n // Start continuous audio capture\n await this.startContinuousCapture();\n\n logger.info(\"[StreamingAudio] Streaming audio capture initialized\");\n } catch (error) {\n logger.error(\"[StreamingAudio] Failed to initialize:\", error);\n throw error;\n }\n }\n\n private async startContinuousCapture(): Promise<void> {\n const platform = process.platform;\n let command: string;\n let args: string[];\n\n if (platform === \"darwin\") {\n // macOS: Use sox for continuous capture\n command = \"sox\";\n args = [\n \"-d\", // default input device\n \"-r\",\n this.config.sampleRate?.toString(),\n \"-c\",\n this.config.channels?.toString(),\n \"-b\",\n \"16\",\n \"-e\",\n \"signed\",\n \"-t\",\n \"raw\",\n \"-\", // output to stdout\n ];\n } else if (platform === \"linux\") {\n // Linux: Use arecord\n command = \"arecord\";\n args = [\n \"-D\",\n this.config.device || \"default\",\n \"-f\",\n \"S16_LE\",\n \"-r\",\n this.config.sampleRate?.toString(),\n \"-c\",\n this.config.channels?.toString(),\n \"-t\",\n \"raw\",\n \"-\", // output to stdout\n ];\n } else if (platform === \"win32\") {\n // Windows: Use ffmpeg\n command = \"ffmpeg\";\n args = [\n \"-f\",\n \"dshow\",\n \"-i\",\n `audio=\"${this.config.device || \"Microphone\"}\"`,\n \"-acodec\",\n \"pcm_s16le\",\n \"-ar\",\n this.config.sampleRate?.toString(),\n \"-ac\",\n this.config.channels?.toString(),\n \"-f\",\n \"s16le\",\n \"pipe:1\", // output to stdout\n ];\n } else {\n throw new Error(`Unsupported platform: ${platform}`);\n }\n\n this.captureProcess = spawn(command, args);\n this.isCapturing = true;\n\n // Handle audio data stream\n this.captureProcess.stdout?.on(\"data\", (chunk: Buffer) => {\n this.processAudioChunk(chunk);\n });\n\n this.captureProcess.stderr?.on(\"data\", (data) => {\n logger.debug(\"[StreamingAudio] Capture stderr:\", data.toString());\n });\n\n this.captureProcess.on(\"error\", (error) => {\n logger.error(\n \"[StreamingAudio] Capture process error:\",\n error instanceof Error ? error.message : String(error),\n );\n this.isCapturing = false;\n });\n\n this.captureProcess.on(\"exit\", (code) => {\n logger.info(\n \"[StreamingAudio] Capture process exited with code:\",\n String(code ?? 0),\n );\n this.isCapturing = false;\n });\n }\n\n private processAudioChunk(chunk: Buffer): void {\n // Calculate audio energy for VAD\n const energy = this.calculateEnergy(chunk);\n const timestamp = Date.now();\n\n // Store chunk\n const audioChunk: AudioChunk = { data: chunk, timestamp, energy };\n\n // Voice Activity Detection\n if (energy > (this.config.vadThreshold ?? 0.01)) {\n if (!this.isSpeaking) {\n // Speech started\n this.isSpeaking = true;\n logger.debug(\"[StreamingAudio] Speech detected, starting recording\");\n this.emit(\"speechStart\");\n\n // Clear any pending response\n if (this.responseTimer) {\n clearTimeout(this.responseTimer);\n this.responseTimer = null;\n logger.debug(\n \"[StreamingAudio] Cancelled pending response due to new speech\",\n );\n }\n }\n\n // Add to buffer\n this.audioBuffer.push(audioChunk);\n\n // Reset silence timer\n if (this.silenceTimer) {\n clearTimeout(this.silenceTimer);\n }\n\n // Start streaming transcription if not already running\n if (!this.transcriptionInProgress) {\n this.startStreamingTranscription();\n }\n } else if (this.isSpeaking) {\n // Currently in speech but detected silence\n this.audioBuffer.push(audioChunk);\n\n // Set timer for end of speech\n if (!this.silenceTimer) {\n this.silenceTimer = setTimeout(() => {\n this.endSpeech();\n }, this.config.silenceTimeout ?? 1500);\n }\n }\n\n // Clean up old chunks (keep last 30 seconds)\n const cutoffTime = timestamp - 30000;\n this.audioBuffer = this.audioBuffer.filter((c) => c.timestamp > cutoffTime);\n }\n\n private calculateEnergy(chunk: Buffer): number {\n // Calculate RMS energy of audio chunk\n let sum = 0;\n const samples = chunk.length / 2; // 16-bit samples\n\n for (let i = 0; i < chunk.length; i += 2) {\n const sample = chunk.readInt16LE(i);\n sum += sample * sample;\n }\n\n const rms = Math.sqrt(sum / samples);\n return rms / 32768; // Normalize to 0-1\n }\n\n private async startStreamingTranscription(): Promise<void> {\n if (this.transcriptionInProgress) {\n return;\n }\n\n this.transcriptionInProgress = true;\n logger.debug(\"[StreamingAudio] Starting streaming transcription\");\n\n try {\n // Get audio data from buffer\n const audioData = this.getRecentAudioData();\n\n if (audioData.length === 0) {\n this.transcriptionInProgress = false;\n return;\n }\n\n // Use streaming transcription if available, otherwise batch\n const result = await this.transcribeAudio(audioData);\n\n if (result?.trim()) {\n this.currentTranscription = result;\n logger.info(`[StreamingAudio] Partial transcription: \"${result}\"`);\n this.emit(\"transcription\", { text: result, isFinal: false });\n }\n } catch (error) {\n logger.error(\"[StreamingAudio] Transcription error:\", error);\n }\n\n this.transcriptionInProgress = false;\n\n // Continue transcription if still speaking\n if (this.isSpeaking) {\n setTimeout(() => this.startStreamingTranscription(), 500);\n }\n }\n\n private endSpeech(): void {\n if (!this.isSpeaking) {\n return;\n }\n\n this.isSpeaking = false;\n this.silenceTimer = null;\n logger.debug(\"[StreamingAudio] Speech ended\");\n this.emit(\"speechEnd\");\n\n // Get final transcription\n this.processFinalTranscription();\n }\n\n private async processFinalTranscription(): Promise<void> {\n const audioData = this.getRecentAudioData();\n\n if (audioData.length === 0) {\n return;\n }\n\n try {\n // Get final transcription\n const finalText = await this.transcribeAudio(audioData);\n\n if (finalText?.trim()) {\n this.currentTranscription = finalText;\n logger.info(`[StreamingAudio] Final transcription: \"${finalText}\"`);\n this.emit(\"transcription\", { text: finalText, isFinal: true });\n\n // Set timer for response generation\n this.responseTimer = setTimeout(() => {\n this.generateResponse(finalText);\n }, this.config.responseDelay ?? 3000);\n }\n } catch (error) {\n logger.error(\"[StreamingAudio] Final transcription error:\", error);\n } finally {\n // Clear audio buffer\n this.audioBuffer = [];\n this.currentTranscription = \"\";\n }\n }\n\n private getRecentAudioData(): Buffer {\n if (this.audioBuffer.length === 0) {\n return Buffer.alloc(0);\n }\n\n // Get audio from start of speech to now\n const startTime = this.audioBuffer[0].timestamp;\n const relevantChunks = this.audioBuffer.filter(\n (c) => c.timestamp >= startTime,\n );\n\n // Combine chunks\n const totalLength = relevantChunks.reduce(\n (sum, c) => sum + c.data.length,\n 0,\n );\n const combined = Buffer.alloc(totalLength);\n let offset = 0;\n\n for (const chunk of relevantChunks) {\n chunk.data.copy(combined, offset);\n offset += chunk.data.length;\n }\n\n return combined;\n }\n\n private async transcribeAudio(audioData: Buffer): Promise<string | null> {\n try {\n // Convert raw audio to WAV format\n const wavBuffer = this.rawToWav(audioData);\n\n // Use runtime transcription model\n const result = await withStandaloneTrajectory(\n this.runtime,\n {\n source: \"plugin-vision:streaming-audio-transcription\",\n metadata: {\n modelType: ModelType.TRANSCRIPTION,\n audioBytes: wavBuffer.byteLength,\n },\n },\n () => this.runtime.useModel(ModelType.TRANSCRIPTION, wavBuffer),\n );\n\n return result as string;\n } catch (error) {\n logger.error(\"[StreamingAudio] Transcription failed:\", error);\n return null;\n }\n }\n\n private rawToWav(rawData: Buffer): Buffer {\n // Create WAV header\n const sampleRate = this.config.sampleRate ?? 16000;\n const channels = this.config.channels ?? 1;\n const bitsPerSample = 16;\n const byteRate = sampleRate * channels * (bitsPerSample / 8);\n const blockAlign = channels * (bitsPerSample / 8);\n const dataSize = rawData.length;\n const fileSize = 36 + dataSize;\n\n const header = Buffer.alloc(44);\n\n // RIFF chunk\n header.write(\"RIFF\", 0);\n header.writeUInt32LE(fileSize, 4);\n header.write(\"WAVE\", 8);\n\n // fmt chunk\n header.write(\"fmt \", 12);\n header.writeUInt32LE(16, 16); // fmt chunk size\n header.writeUInt16LE(1, 20); // PCM format\n header.writeUInt16LE(channels, 22);\n header.writeUInt32LE(sampleRate, 24);\n header.writeUInt32LE(byteRate, 28);\n header.writeUInt16LE(blockAlign, 32);\n header.writeUInt16LE(bitsPerSample, 34);\n\n // data chunk\n header.write(\"data\", 36);\n header.writeUInt32LE(dataSize, 40);\n\n return Buffer.concat([header, rawData]);\n }\n\n private async generateResponse(transcription: string): Promise<void> {\n this.responseTimer = null;\n\n try {\n // Create audio memory\n await this.createAudioMemory(transcription);\n\n // Emit event for response generation\n this.emit(\"utteranceComplete\", transcription);\n } catch (error) {\n logger.error(\"[StreamingAudio] Response generation error:\", error);\n }\n }\n\n private async createAudioMemory(transcription: string): Promise<void> {\n try {\n const _memory = {\n content: {\n text: `[Audio] ${transcription}`,\n type: \"audio_transcription\",\n source: \"microphone_streaming\",\n timestamp: Date.now(),\n },\n metadata: {\n isAudioTranscription: true,\n streaming: true,\n },\n };\n\n logger.info(\"[StreamingAudio] Audio transcription stored in context\");\n } catch (error) {\n logger.error(\"[StreamingAudio] Failed to create audio memory:\", error);\n }\n }\n\n async stop(): Promise<void> {\n logger.info(\"[StreamingAudio] Stopping audio capture...\");\n\n if (this.captureProcess) {\n this.captureProcess.kill();\n this.captureProcess = null;\n }\n\n if (this.silenceTimer) {\n clearTimeout(this.silenceTimer);\n this.silenceTimer = null;\n }\n\n if (this.responseTimer) {\n clearTimeout(this.responseTimer);\n this.responseTimer = null;\n }\n\n this.isCapturing = false;\n this.isSpeaking = false;\n this.audioBuffer = [];\n\n logger.info(\"[StreamingAudio] Audio capture stopped\");\n }\n\n isActive(): boolean {\n return this.isCapturing;\n }\n\n getCurrentTranscription(): string {\n return this.currentTranscription;\n }\n\n isSpeechActive(): boolean {\n return this.isSpeaking;\n }\n}\n",
12
+ "import {\n type IAgentRuntime,\n createUniqueUuid,\n logger,\n type UUID,\n} from \"@elizaos/core\";\nimport type {\n BoundingBox,\n DetectedObject,\n PersonInfo,\n TrackedEntity,\n WorldState,\n} 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(\n person,\n faceProfiles?.get(person.id),\n currentTime,\n );\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(\n person.boundingBox,\n \"person\",\n faceProfileId,\n );\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(\n obj: DetectedObject,\n timestamp: number,\n ): 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(\n `[EntityTracker] New object entity created: ${entityId} (${obj.type})`,\n );\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 (\n entityType === \"person\" &&\n faceProfileId &&\n entity.attributes.faceId\n ) {\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(\n (center1.x - center2.x) ** 2 + (center1.y - center2.y) ** 2,\n );\n }\n\n private updateWorldState(\n seenEntityIds: Set<string>,\n timestamp: number,\n ): 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 (\n !seenEntityIds.has(entityId) &&\n this.worldState.activeEntities.includes(entityId)\n ) {\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 // Sync detected entities with the runtime's entity system\n for (const entity of frameEntities) {\n // Convert the human-readable tracker ID (e.g. \"person-123-abc\") to a\n // deterministic UUID that PostgreSQL accepts. The same local ID always\n // maps to the same UUID for a given agent, so updates stay consistent.\n const entityUuid = createUniqueUuid(runtime, entity.id);\n\n const elizaEntity = {\n id: entityUuid,\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 try {\n const existing = await runtime.getEntityById(entityUuid);\n if (!existing) {\n await runtime.createEntity(elizaEntity);\n logger.debug(\n `[EntityTracker] Created entity ${entity.id} (${entityUuid}) in runtime`,\n );\n } else {\n await runtime.updateEntity({\n ...elizaEntity,\n id: entityUuid,\n });\n logger.debug(\n `[EntityTracker] Updated entity ${entity.id} (${entityUuid}) in runtime`,\n );\n }\n } catch (err) {\n logger.debug(\n `[EntityTracker] Could not sync entity ${entity.id}: ${err instanceof Error ? err.message : String(err)}`,\n );\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<{\n entity: TrackedEntity;\n leftAt: number;\n }>;\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(\n `[EntityTracker] Assigned name \"${name}\" to entity ${entityId}`,\n );\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",
13
+ "import * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { logger } from \"@elizaos/core\";\nimport * as faceapi from \"face-api.js\";\nimport type { FaceLibrary, FaceProfile } from \"./types\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Dynamic imports for optional dependencies\n// Canvas package types differ from DOM types but are runtime-compatible with face-api.js\nlet CanvasModule: typeof import(\"canvas\") | undefined;\n\n/**\n * Type helpers for node-canvas to face-api.js compatibility.\n * The canvas package provides Node.js implementations that are runtime-compatible\n * with face-api.js, but have different TypeScript types than DOM equivalents.\n */\ntype FaceApiEnv = {\n Canvas: typeof HTMLCanvasElement;\n Image: typeof HTMLImageElement;\n ImageData: typeof ImageData;\n};\n\n/**\n * Adapter type for node-canvas Canvas to HTMLCanvasElement.\n * Runtime-compatible but TypeScript types differ.\n */\ntype CanvasAdapter = import(\"canvas\").Canvas & HTMLCanvasElement;\n\nfunction asCanvasEnv(canvas: typeof import(\"canvas\")): FaceApiEnv {\n return {\n // node-canvas types don't match DOM types but are runtime-compatible with face-api.js\n Canvas: canvas.Canvas as never,\n Image: canvas.Image as never,\n ImageData: canvas.ImageData as typeof ImageData,\n };\n}\n\nfunction asHTMLCanvasElement(\n canvas: import(\"canvas\").Canvas,\n): HTMLCanvasElement {\n // node-canvas Canvas is runtime-compatible with HTMLCanvasElement\n return canvas as CanvasAdapter as HTMLCanvasElement;\n}\n\nasync function initializeCanvas() {\n try {\n CanvasModule = await import(\"canvas\");\n\n // Polyfill for face-api.js - node-canvas is runtime-compatible with face-api.js\n faceapi.env.monkeyPatch(asCanvasEnv(CanvasModule));\n } catch (error) {\n logger.error(\"[FaceRecognition] Canvas module not available:\", error);\n throw new Error(\n \"Canvas module is required for face recognition. Install with: npm install canvas\",\n );\n }\n}\n\nexport class FaceRecognition {\n private initialized = false;\n private faceLibrary: FaceLibrary = {\n faces: new Map(),\n embeddings: new Map(),\n };\n private modelPath = path.join(__dirname, \"..\", \"models\", \"face-api\");\n\n // Thresholds\n private readonly FACE_MATCH_THRESHOLD = 0.6; // Euclidean distance threshold\n private readonly MIN_FACE_SIZE = 50; // Minimum face size in pixels\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n try {\n logger.info(\"[FaceRecognition] Loading face detection models...\");\n\n // Initialize canvas first\n await initializeCanvas();\n\n // Load face-api.js models\n await faceapi.nets.ssdMobilenetv1.loadFromDisk(this.modelPath);\n await faceapi.nets.faceLandmark68Net.loadFromDisk(this.modelPath);\n await faceapi.nets.faceRecognitionNet.loadFromDisk(this.modelPath);\n await faceapi.nets.faceExpressionNet.loadFromDisk(this.modelPath);\n await faceapi.nets.ageGenderNet.loadFromDisk(this.modelPath);\n\n this.initialized = true;\n logger.info(\"[FaceRecognition] Models loaded successfully\");\n } catch (error) {\n logger.error(\"[FaceRecognition] Failed to load models:\", error);\n logger.info(\n \"[FaceRecognition] Download models from: https://github.com/justadudewhohacks/face-api.js-models\",\n );\n throw error;\n }\n }\n\n async detectFaces(\n imageData: Buffer,\n width: number,\n height: number,\n ): Promise<\n Array<{\n detection: faceapi.FaceDetection;\n landmarks: faceapi.FaceLandmarks68;\n descriptor: Float32Array;\n expressions: faceapi.FaceExpressions;\n ageGender?: { age: number; gender: string; genderProbability: number };\n }>\n > {\n if (!this.initialized) {\n await this.initialize();\n }\n\n // Validate input parameters\n if (!imageData || imageData.length === 0 || width <= 0 || height <= 0) {\n logger.warn(\n `[FaceRecognition] Invalid input parameters: dataLength=${imageData?.length || 0}, width=${width}, height=${height}`,\n );\n return [];\n }\n\n // Validate that the buffer size matches expected dimensions\n const expectedSize = width * height * 4; // RGBA\n if (imageData.length !== expectedSize) {\n logger.warn(\n `[FaceRecognition] Buffer size mismatch: expected=${expectedSize}, actual=${imageData.length}, width=${width}, height=${height}`,\n );\n return [];\n }\n\n try {\n if (!CanvasModule) {\n throw new Error(\n \"Canvas module not initialized. Call initialize() first.\",\n );\n }\n // Create canvas from image data\n const canvas = new CanvasModule.Canvas(width, height);\n const ctx = canvas.getContext(\"2d\");\n const imageDataObj = new CanvasModule.ImageData(\n new Uint8ClampedArray(imageData),\n width,\n height,\n );\n ctx.putImageData(imageDataObj, 0, 0);\n\n // Detect faces with full analysis\n // face-api.js accepts HTMLCanvasElement or compatible canvas (node-canvas works)\n const detections = await faceapi\n .detectAllFaces(\n asHTMLCanvasElement(canvas),\n new faceapi.SsdMobilenetv1Options({\n minConfidence: 0.5,\n maxResults: 10,\n }),\n )\n .withFaceLandmarks()\n .withFaceDescriptors()\n .withFaceExpressions()\n .withAgeAndGender();\n\n return detections.filter(\n (d: {\n detection: {\n box: {\n width: number;\n height: number;\n };\n };\n }) => {\n const box = d.detection.box;\n return (\n box.width >= this.MIN_FACE_SIZE && box.height >= this.MIN_FACE_SIZE\n );\n },\n );\n } catch (error) {\n logger.error(\"[FaceRecognition] Face detection failed:\", error);\n return [];\n }\n }\n\n async recognizeFace(\n descriptor: Float32Array,\n ): Promise<{ profileId: string; distance: number } | null> {\n let bestMatch: { profileId: string; distance: number } | null = null;\n let minDistance = Infinity;\n\n // Compare with all known faces\n for (const [profileId, embeddings] of this.faceLibrary.embeddings) {\n for (const knownEmbedding of embeddings) {\n const distance = this.euclideanDistance(descriptor, knownEmbedding);\n\n if (distance < this.FACE_MATCH_THRESHOLD && distance < minDistance) {\n minDistance = distance;\n bestMatch = { profileId, distance };\n }\n }\n }\n\n return bestMatch;\n }\n\n async addOrUpdateFace(\n descriptor: Float32Array,\n attributes?: Partial<FaceProfile>,\n ): Promise<string> {\n // Check if this face already exists\n const match = await this.recognizeFace(descriptor);\n\n if (match) {\n // Update existing profile\n const profile = this.faceLibrary.faces.get(match.profileId);\n if (!profile) {\n throw new Error(\n `Profile not found for matched profileId: ${match.profileId}`,\n );\n }\n profile.lastSeen = Date.now();\n profile.seenCount++;\n\n // Add new embedding for better recognition\n const embeddings = this.faceLibrary.embeddings.get(match.profileId);\n if (!embeddings) {\n throw new Error(\n `Embeddings not found for matched profileId: ${match.profileId}`,\n );\n }\n if (embeddings.length < 10) {\n // Keep up to 10 embeddings per person\n embeddings.push(Array.from(descriptor));\n }\n\n // Update attributes if provided\n if (attributes) {\n Object.assign(profile, attributes);\n }\n\n return match.profileId;\n } else {\n // Create new profile\n const profileId = `face-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n const profile: FaceProfile = {\n id: profileId,\n embeddings: [Array.from(descriptor)],\n firstSeen: Date.now(),\n lastSeen: Date.now(),\n seenCount: 1,\n ...attributes,\n };\n\n this.faceLibrary.faces.set(profileId, profile);\n this.faceLibrary.embeddings.set(profileId, [Array.from(descriptor)]);\n\n logger.info(`[FaceRecognition] New face registered: ${profileId}`);\n return profileId;\n }\n }\n\n getFaceProfile(profileId: string): FaceProfile | undefined {\n return this.faceLibrary.faces.get(profileId);\n }\n\n getAllProfiles(): FaceProfile[] {\n return Array.from(this.faceLibrary.faces.values());\n }\n\n private euclideanDistance(a: Float32Array | number[], b: number[]): number {\n let sum = 0;\n const aArray = Array.from(a);\n for (let i = 0; i < aArray.length; i++) {\n sum += (aArray[i] - b[i]) ** 2;\n }\n return Math.sqrt(sum);\n }\n\n // Persistence methods\n async saveFaceLibrary(path: string): Promise<void> {\n const data = {\n faces: Array.from(this.faceLibrary.faces.entries()),\n embeddings: Array.from(this.faceLibrary.embeddings.entries()),\n };\n\n const fs = await import(\"node:fs/promises\");\n await fs.writeFile(path, JSON.stringify(data, null, 2));\n logger.info(`[FaceRecognition] Face library saved to ${path}`);\n }\n\n async loadFaceLibrary(path: string): Promise<void> {\n try {\n const fs = await import(\"node:fs/promises\");\n const data = JSON.parse(await fs.readFile(path, \"utf-8\"));\n\n this.faceLibrary.faces = new Map(data.faces);\n this.faceLibrary.embeddings = new Map(data.embeddings);\n\n logger.info(\n `[FaceRecognition] Loaded ${this.faceLibrary.faces.size} face profiles`,\n );\n } catch (error) {\n logger.warn(\"[FaceRecognition] Could not load face library:\", error);\n }\n }\n}\n",
14
+ "import { logger } from \"@elizaos/core\";\nimport { Florence2Local } from \"./florence2-local\";\nimport type { BoundingBox, Florence2Result, ScreenTile } from \"./types\";\n\nexport class Florence2Model {\n private initialized = false;\n private localModel: Florence2Local;\n\n constructor() {\n this.localModel = new Florence2Local();\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n try {\n logger.info(\n \"[Florence2] Initializing local Florence-2 model with TensorFlow.js...\",\n );\n\n await this.localModel.initialize();\n\n this.initialized = true;\n logger.info(\"[Florence2] Local model initialized successfully\");\n } catch (error) {\n logger.error(\"[Florence2] Failed to initialize local model:\", error);\n // Don't throw - we have good fallbacks\n this.initialized = true;\n logger.warn(\"[Florence2] Running with enhanced fallback mode\");\n }\n }\n\n async analyzeTile(tile: ScreenTile): Promise<Florence2Result> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n if (!tile.data) {\n throw new Error(\"Tile has no image data\");\n }\n\n try {\n // Use local model\n try {\n const result = await this.localModel.analyzeImage(tile.data);\n logger.debug(`[Florence2] Analyzed tile ${tile.id}: ${result.caption}`);\n return result;\n } catch (_modelError) {\n logger.warn(\n \"[Florence2] Local model analysis failed, falling back:\",\n _modelError,\n );\n }\n\n // Fall back to mock analysis\n const result = await this.mockAnalyze(tile);\n logger.debug(\n `[Florence2] Mock analyzed tile ${tile.id}: ${result.caption}`,\n );\n return result;\n } catch (error) {\n logger.error(\"[Florence2] Analysis failed:\", error);\n throw error;\n }\n }\n\n async analyzeImage(imageBuffer: Buffer): Promise<Florence2Result> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n try {\n // Use local model\n try {\n const result = await this.localModel.analyzeImage(imageBuffer);\n logger.debug(`[Florence2] Analyzed image: ${result.caption}`);\n return result;\n } catch (_modelError) {\n logger.warn(\n \"[Florence2] Local model analysis failed, falling back:\",\n _modelError,\n );\n }\n\n // Fall back to mock analysis\n const result = await this.mockAnalyzeBuffer(imageBuffer);\n logger.debug(`[Florence2] Mock analyzed image: ${result.caption}`);\n return result;\n } catch (error) {\n logger.error(\"[Florence2] Image analysis failed:\", error);\n throw error;\n }\n }\n\n private async mockAnalyze(tile: ScreenTile): Promise<Florence2Result> {\n // Mock implementation that simulates Florence-2 output\n // In production, this would be replaced with actual API calls\n\n const isUpperRegion = tile.row < 2;\n const isLeftRegion = tile.col < 2;\n\n // Simulate different UI regions\n let caption = \"Desktop screen region\";\n const objects: Array<{\n label: string;\n bbox: BoundingBox;\n confidence: number;\n }> = [];\n const regions: Array<{ description: string; bbox: BoundingBox }> = [];\n const tags: string[] = [];\n\n if (isUpperRegion) {\n caption = \"Application window with menu bar\";\n objects.push({\n label: \"window\",\n bbox: { x: 0, y: 0, width: tile.width, height: 50 },\n confidence: 0.9,\n });\n objects.push({\n label: \"menu_bar\",\n bbox: { x: 0, y: 0, width: tile.width, height: 30 },\n confidence: 0.85,\n });\n tags.push(\"ui\", \"application\", \"desktop\");\n }\n\n if (isLeftRegion) {\n caption = \"Sidebar or navigation area\";\n objects.push({\n label: \"sidebar\",\n bbox: { x: 0, y: 0, width: 100, height: tile.height },\n confidence: 0.8,\n });\n tags.push(\"navigation\", \"sidebar\");\n }\n\n // Add some common UI elements\n const buttonCount = Math.floor(Math.random() * 3) + 1;\n for (let i = 0; i < buttonCount; i++) {\n objects.push({\n label: \"button\",\n bbox: {\n x: Math.random() * (tile.width - 100),\n y: Math.random() * (tile.height - 40),\n width: 100,\n height: 40,\n },\n confidence: 0.7 + Math.random() * 0.2,\n });\n }\n\n // Add text regions\n const textRegions = Math.floor(Math.random() * 2) + 1;\n for (let i = 0; i < textRegions; i++) {\n regions.push({\n description: \"Text content area\",\n bbox: {\n x: Math.random() * (tile.width - 200),\n y: Math.random() * (tile.height - 100),\n width: 200,\n height: 100,\n },\n });\n }\n\n tags.push(\"screen\", \"interface\", \"computer\");\n\n return {\n caption,\n objects,\n regions,\n tags,\n };\n }\n\n async detectUIElements(imageBuffer: Buffer): Promise<\n Array<{\n type: string;\n bbox: BoundingBox;\n confidence: number;\n text?: string;\n }>\n > {\n if (!this.initialized) {\n await this.initialize();\n }\n\n try {\n // Use local model to analyze image\n let result: Florence2Result;\n\n try {\n result = await this.localModel.analyzeImage(imageBuffer);\n } catch (_modelError) {\n logger.warn(\n \"[Florence2] Local model failed for UI detection, using fallback\",\n );\n result = await this.mockAnalyzeBuffer(imageBuffer);\n }\n\n // Convert Florence-2 objects to UI elements\n return (result.objects || []).map((obj) => ({\n type: this.mapToUIElementType(obj.label),\n bbox: obj.bbox,\n confidence: obj.confidence,\n }));\n } catch (error) {\n logger.error(\"[Florence2] UI element detection failed:\", error);\n return [];\n }\n }\n\n private async mockAnalyzeBuffer(\n _imageBuffer: Buffer,\n ): Promise<Florence2Result> {\n // Enhanced mock for when API is not available\n // Provides more realistic descriptions based on common scenarios\n\n const scenarios = [\n {\n caption: \"Indoor scene with a person in front of a computer\",\n objects: [\n {\n label: \"person\",\n bbox: { x: 300, y: 200, width: 200, height: 300 },\n confidence: 0.9,\n },\n {\n label: \"computer\",\n bbox: { x: 400, y: 350, width: 150, height: 100 },\n confidence: 0.85,\n },\n {\n label: \"desk\",\n bbox: { x: 350, y: 400, width: 250, height: 100 },\n confidence: 0.8,\n },\n ],\n tags: [\"indoor\", \"office\", \"workspace\", \"person\", \"computer\"],\n },\n {\n caption: \"Room interior with furniture and lighting\",\n objects: [\n {\n label: \"chair\",\n bbox: { x: 200, y: 300, width: 100, height: 150 },\n confidence: 0.85,\n },\n {\n label: \"table\",\n bbox: { x: 350, y: 350, width: 150, height: 100 },\n confidence: 0.8,\n },\n {\n label: \"lamp\",\n bbox: { x: 500, y: 200, width: 50, height: 100 },\n confidence: 0.75,\n },\n ],\n tags: [\"indoor\", \"room\", \"furniture\", \"interior\"],\n },\n {\n caption: \"Person working at a desk with computer monitor\",\n objects: [\n {\n label: \"person\",\n bbox: { x: 250, y: 150, width: 250, height: 350 },\n confidence: 0.92,\n },\n {\n label: \"monitor\",\n bbox: { x: 450, y: 300, width: 120, height: 80 },\n confidence: 0.88,\n },\n {\n label: \"keyboard\",\n bbox: { x: 430, y: 380, width: 100, height: 30 },\n confidence: 0.82,\n },\n ],\n tags: [\"person\", \"working\", \"computer\", \"desk\", \"office\"],\n },\n ];\n\n // Randomly select a scenario for variety\n const scenario = scenarios[Math.floor(Math.random() * scenarios.length)];\n\n return {\n caption: scenario.caption,\n objects: scenario.objects,\n regions: [],\n tags: scenario.tags,\n };\n }\n\n private mapToUIElementType(label: string): string {\n const mapping: Record<string, string> = {\n button: \"button\",\n text_field: \"input\",\n text_area: \"textarea\",\n checkbox: \"checkbox\",\n radio_button: \"radio\",\n dropdown: \"select\",\n menu: \"menu\",\n menu_bar: \"menubar\",\n toolbar: \"toolbar\",\n window: \"window\",\n dialog: \"dialog\",\n icon: \"icon\",\n image: \"image\",\n video: \"video\",\n link: \"link\",\n heading: \"heading\",\n paragraph: \"text\",\n list: \"list\",\n table: \"table\",\n scrollbar: \"scrollbar\",\n tab: \"tab\",\n panel: \"panel\",\n };\n\n return mapping[label.toLowerCase()] || \"unknown\";\n }\n\n async generateSceneGraph(tiles: ScreenTile[]): Promise<{\n nodes: Array<{\n id: string;\n type: string;\n label: string;\n position: BoundingBox;\n }>;\n edges: Array<{ source: string; target: string; relation: string }>;\n }> {\n const nodes: Array<{\n id: string;\n type: string;\n label: string;\n position: BoundingBox;\n }> = [];\n const edges: Array<{ source: string; target: string; relation: string }> =\n [];\n\n // Analyze each tile\n for (const tile of tiles) {\n if (!tile.data) {\n continue;\n }\n\n const analysis = await this.analyzeTile(tile);\n\n // Add objects as nodes\n if (analysis.objects) {\n for (const obj of analysis.objects) {\n const nodeId = `${tile.id}-${obj.label}-${nodes.length}`;\n nodes.push({\n id: nodeId,\n type: obj.label,\n label: obj.label,\n position: {\n x: tile.x + obj.bbox.x,\n y: tile.y + obj.bbox.y,\n width: obj.bbox.width,\n height: obj.bbox.height,\n },\n });\n }\n }\n }\n\n // Infer spatial relationships\n for (let i = 0; i < nodes.length; i++) {\n for (let j = i + 1; j < nodes.length; j++) {\n const relation = this.inferSpatialRelation(\n nodes[i].position,\n nodes[j].position,\n );\n if (relation) {\n edges.push({\n source: nodes[i].id,\n target: nodes[j].id,\n relation,\n });\n }\n }\n }\n\n return { nodes, edges };\n }\n\n private inferSpatialRelation(\n box1: BoundingBox,\n box2: BoundingBox,\n ): string | null {\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 // Check containment\n if (this.contains(box1, box2)) {\n return \"contains\";\n }\n if (this.contains(box2, box1)) {\n return \"contained_by\";\n }\n\n // Check overlap\n if (this.overlaps(box1, box2)) {\n return \"overlaps\";\n }\n\n // Check adjacency and direction\n const dx = center2.x - center1.x;\n const dy = center2.y - center1.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n if (distance < 100) {\n // Close proximity\n if (Math.abs(dx) > Math.abs(dy)) {\n return dx > 0 ? \"right_of\" : \"left_of\";\n } else {\n return dy > 0 ? \"below\" : \"above\";\n }\n }\n\n return null;\n }\n\n private contains(box1: BoundingBox, box2: BoundingBox): boolean {\n return (\n box1.x <= box2.x &&\n box1.y <= box2.y &&\n box1.x + box1.width >= box2.x + box2.width &&\n box1.y + box1.height >= box2.y + box2.height\n );\n }\n\n private overlaps(box1: BoundingBox, box2: BoundingBox): boolean {\n return !(\n box1.x + box1.width < box2.x ||\n box2.x + box2.width < box1.x ||\n box1.y + box1.height < box2.y ||\n box2.y + box2.height < box1.y\n );\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n async dispose(): Promise<void> {\n // Clean up resources if needed\n this.initialized = false;\n logger.info(\"[Florence2] Model disposed\");\n }\n}\n",
15
+ "import { logger } from \"@elizaos/core\";\nimport sharp from \"sharp\";\nimport type { Florence2Result } from \"./types\";\n\n// Lazy-loaded TensorFlow.js — the native addon may not be available.\nlet tf: typeof import(\"@tensorflow/tfjs-node\") | null = null;\n\nasync function ensureTf(): Promise<boolean> {\n if (tf) return true;\n try {\n tf = await import(\"@tensorflow/tfjs-node\");\n return true;\n } catch {\n logger.warn(\n \"[Florence2Local] TensorFlow.js native addon not available — using heuristic analysis.\",\n );\n return false;\n }\n}\n\ninterface VisionModelConfig {\n modelUrl?: string;\n cacheDir?: string;\n}\n\ninterface ResolvedVisionModelConfig {\n modelUrl: string;\n cacheDir: string;\n}\n\n/**\n * Local vision model for basic image analysis using MobileNet.\n * Provides caption generation and basic scene understanding capabilities.\n */\nexport class Florence2Local {\n private model: {\n predict: (\n input: ReturnType<NonNullable<typeof tf>[\"tensor\"]>,\n ) => ReturnType<NonNullable<typeof tf>[\"tensor\"]>;\n dispose: () => void;\n } | null = null;\n private initialized = false;\n private config: ResolvedVisionModelConfig;\n\n constructor(config?: VisionModelConfig) {\n this.config = {\n modelUrl:\n config?.modelUrl ||\n \"https://tfhub.dev/google/tfjs-model/imagenet/mobilenet_v3_small_100_224/feature_vector/5/default/1\",\n cacheDir: config?.cacheDir || \"./models/cache\",\n };\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n const tfAvailable = await ensureTf();\n if (!tfAvailable || !tf) {\n // Continue without model — will use heuristic-based analysis\n this.initialized = true;\n return;\n }\n\n try {\n logger.info(\n \"[VisionModel] Initializing MobileNet model for image analysis...\",\n );\n\n this.model = (await tf.loadGraphModel(\n this.config.modelUrl,\n )) as typeof this.model;\n\n this.initialized = true;\n logger.info(\"[VisionModel] Model initialized successfully\");\n } catch (error) {\n logger.error(\"[VisionModel] Failed to initialize model:\", error);\n // Continue without model - will use heuristic-based analysis\n this.initialized = true;\n }\n }\n\n async analyzeImage(imageBuffer: Buffer): Promise<Florence2Result> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n // If TF isn't available or model didn't load, skip directly to fallback\n if (!tf || !this.model) {\n return await this.enhancedFallback(imageBuffer);\n }\n\n try {\n // Preprocess image\n const preprocessed = await this.preprocessImage(imageBuffer);\n\n // Run inference\n const predictions = await this.runInference(preprocessed);\n (preprocessed as { dispose?: () => void }).dispose?.();\n\n return this.parseModelOutput(\n predictions as Parameters<typeof this.parseModelOutput>[0],\n );\n } catch (error) {\n logger.error(\"[VisionModel] Analysis failed:\", error);\n return await this.enhancedFallback(imageBuffer);\n }\n }\n\n private async preprocessImage(imageBuffer: Buffer) {\n if (!tf) throw new Error(\"TensorFlow.js not available\");\n\n // Resize and normalize image for model input\n const resized = await sharp(imageBuffer)\n .resize(224, 224) // MobileNet uses 224x224\n .raw()\n .toBuffer();\n\n // Convert to tensor and normalize\n const tensor = tf.node.decodeImage(resized, 3);\n const normalized = tf.div(tensor, 255.0);\n\n return normalized;\n }\n\n private async runInference(input: {\n expandDims: (axis: number) => { dispose: () => void };\n }) {\n if (!this.model) {\n throw new Error(\"Model not loaded\");\n }\n\n // Add batch dimension\n const batched = input.expandDims(0);\n\n // Run model\n const output = this.model.predict(\n batched as Parameters<typeof this.model.predict>[0],\n );\n\n batched.dispose();\n\n return output;\n }\n\n private async parseModelOutput(predictions: {\n array: () => Promise<number[][]>;\n dispose: () => void;\n }): Promise<Florence2Result> {\n const values = await predictions.array();\n predictions.dispose();\n\n const caption = this.generateCaptionFromFeatures(values);\n\n return {\n caption,\n objects: [],\n regions: [],\n tags: this.extractTagsFromCaption(caption),\n };\n }\n\n private generateCaptionFromFeatures(features: number[][]): string {\n const scenes = [\n \"Indoor scene with various objects visible\",\n \"Person in a room with furniture\",\n \"Computer workspace with monitor and desk\",\n \"Living space with natural lighting\",\n \"Office environment with equipment\",\n ];\n\n const index = Math.abs(features[0][0]) * scenes.length;\n return scenes[Math.floor(index) % scenes.length];\n }\n\n private extractTagsFromCaption(caption: string): string[] {\n const words = caption.toLowerCase().split(/\\s+/);\n const validTags = [\n \"indoor\",\n \"outdoor\",\n \"person\",\n \"computer\",\n \"desk\",\n \"office\",\n \"room\",\n \"furniture\",\n \"monitor\",\n \"workspace\",\n ];\n return words.filter((word) => validTags.includes(word));\n }\n\n private async enhancedFallback(\n imageBuffer: Buffer,\n ): Promise<Florence2Result> {\n // Analyze image properties for better fallback\n const metadata = await sharp(imageBuffer).metadata();\n const stats = await sharp(imageBuffer).stats();\n\n // Determine scene type based on image characteristics\n const brightness =\n (stats.channels[0].mean +\n stats.channels[1].mean +\n stats.channels[2].mean) /\n 3;\n const isIndoor = brightness < 180; // Simplified heuristic\n\n // Generate contextual caption\n let caption = isIndoor ? \"Indoor scene\" : \"Outdoor scene\";\n\n // Add more context based on image properties\n if (metadata.width && metadata.height) {\n const aspectRatio = metadata.width / metadata.height;\n if (aspectRatio > 1.5) {\n caption += \" with wide field of view\";\n } else if (aspectRatio < 0.7) {\n caption += \" in portrait orientation\";\n }\n }\n\n // Detect dominant colors for additional context\n const dominantColor = stats.dominant;\n if (\n dominantColor.r > 200 &&\n dominantColor.g > 200 &&\n dominantColor.b > 200\n ) {\n caption += \", well-lit environment\";\n } else if (\n dominantColor.r < 100 &&\n dominantColor.g < 100 &&\n dominantColor.b < 100\n ) {\n caption += \", dimly lit conditions\";\n }\n\n return {\n caption,\n objects: [],\n regions: [],\n tags: this.extractTagsFromCaption(caption),\n };\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n async dispose(): Promise<void> {\n if (this.model) {\n this.model.dispose();\n this.model = null;\n }\n this.initialized = false;\n logger.info(\"[VisionModel] Model disposed\");\n }\n}\n",
16
+ "import { logger } from \"@elizaos/core\";\nimport { RealOCRService } from \"./ocr-service-real\";\nimport type { BoundingBox, OCRResult, ScreenTile } from \"./types\";\n\nexport class OCRService {\n private realOCR: RealOCRService | null = null;\n private initialized = false;\n private useFallback = false;\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n try {\n logger.info(\"[OCR] Initializing OCR service...\");\n\n // Try to use real OCR first\n this.realOCR = new RealOCRService();\n await this.realOCR.initialize();\n\n this.initialized = true;\n this.useFallback = false;\n logger.info(\"[OCR] Real OCR service initialized successfully\");\n } catch (error) {\n logger.error(\"[OCR] Failed to initialize real OCR:\", error);\n\n // Fallback to basic OCR simulation\n logger.warn(\"[OCR] Using fallback OCR implementation\");\n this.useFallback = true;\n this.initialized = true;\n }\n }\n\n async extractText(imageBuffer: Buffer): Promise<OCRResult> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n // Use real OCR if available\n if (this.realOCR && !this.useFallback) {\n try {\n return await this.realOCR.extractText(imageBuffer);\n } catch (error) {\n logger.error(\"[OCR] Real OCR failed, falling back:\", error);\n this.useFallback = true;\n }\n }\n\n // Fallback implementation\n return this.fallbackOCR(imageBuffer);\n }\n\n async extractFromTile(tile: ScreenTile): Promise<OCRResult> {\n if (!tile.data) {\n return {\n text: \"\",\n blocks: [],\n fullText: \"\",\n };\n }\n\n return this.extractText(tile.data);\n }\n\n async extractFromImage(imageBuffer: Buffer): Promise<OCRResult> {\n return this.extractText(imageBuffer);\n }\n\n private async fallbackOCR(_imageBuffer: Buffer): Promise<OCRResult> {\n // Fallback implementation for when Tesseract is not available\n logger.debug(\"[OCR] Using fallback OCR implementation\");\n\n const blocks: Array<{\n text: string;\n bbox: BoundingBox;\n confidence: number;\n words?: Array<{\n text: string;\n bbox: BoundingBox;\n confidence: number;\n }>;\n }> = [];\n\n // Simulate finding common UI text\n const mockTexts = [\n {\n text: \"File Edit View Window Help\",\n x: 10,\n y: 5,\n width: 300,\n height: 20,\n },\n {\n text: \"Welcome to the application\",\n x: 100,\n y: 100,\n width: 400,\n height: 40,\n },\n {\n text: \"Click here to continue\",\n x: 200,\n y: 300,\n width: 200,\n height: 30,\n },\n ];\n\n for (const mock of mockTexts) {\n blocks.push({\n text: mock.text,\n bbox: { x: mock.x, y: mock.y, width: mock.width, height: mock.height },\n confidence: 0.85 + Math.random() * 0.1,\n });\n }\n\n const fullText = blocks.map((b) => b.text).join(\"\\n\");\n\n return {\n text: fullText,\n blocks,\n fullText,\n };\n }\n\n async extractStructuredData(imageBuffer: Buffer): Promise<{\n tables?: Array<{ rows: string[][]; bbox: BoundingBox }>;\n forms?: Array<{ label: string; value: string; bbox: BoundingBox }>;\n lists?: Array<{ items: string[]; bbox: BoundingBox }>;\n }> {\n if (this.realOCR && !this.useFallback) {\n try {\n return await this.realOCR.extractStructuredData(imageBuffer);\n } catch (error) {\n logger.error(\"[OCR] Structured data extraction failed:\", error);\n }\n }\n\n // Fallback: return empty structured data\n return {\n tables: [],\n forms: [],\n lists: [],\n };\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n async dispose(): Promise<void> {\n if (this.realOCR) {\n await this.realOCR.dispose();\n this.realOCR = null;\n }\n this.initialized = false;\n this.useFallback = false;\n logger.info(\"[OCR] Service disposed\");\n }\n}\n",
17
+ "import { logger } from \"@elizaos/core\";\nimport sharp from \"sharp\";\nimport Tesseract from \"tesseract.js\";\nimport type { BoundingBox, OCRResult, ScreenTile } from \"./types\";\n\nexport class RealOCRService {\n private worker: Tesseract.Worker | null = null;\n private initialized = false;\n private initPromise: Promise<void> | null = null;\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n // Prevent multiple initializations\n if (this.initPromise) {\n return this.initPromise;\n }\n\n this.initPromise = this._initialize();\n return this.initPromise;\n }\n\n private async _initialize(): Promise<void> {\n try {\n logger.info(\"[RealOCR] Initializing Tesseract.js...\");\n\n // Create worker\n this.worker = await Tesseract.createWorker(\"eng\", 1, {\n logger: (m) => {\n if (m.status === \"recognizing text\") {\n logger.debug(\n `[RealOCR] Progress: ${(m.progress * 100).toFixed(1)}%`,\n );\n }\n },\n });\n\n this.initialized = true;\n logger.info(\"[RealOCR] Tesseract.js initialized successfully\");\n } catch (error) {\n logger.error(\"[RealOCR] Failed to initialize:\", error);\n throw error;\n }\n }\n\n async extractText(imageBuffer: Buffer): Promise<OCRResult> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n if (!this.worker) {\n throw new Error(\"OCR worker not initialized\");\n }\n\n try {\n // Preprocess image for better OCR\n const processedBuffer = await this.preprocessImage(imageBuffer);\n\n // Perform OCR\n const result = await this.worker.recognize(processedBuffer);\n\n // Convert Tesseract result to our format\n return this.convertTesseractResult(result);\n } catch (error) {\n logger.error(\"[RealOCR] Text extraction failed:\", error);\n throw error;\n }\n }\n\n async extractFromTile(tile: ScreenTile): Promise<OCRResult> {\n if (!tile.data) {\n return {\n text: \"\",\n blocks: [],\n fullText: \"\",\n };\n }\n\n return this.extractText(tile.data);\n }\n\n private async preprocessImage(imageBuffer: Buffer): Promise<Buffer> {\n try {\n // Enhance image for better OCR results\n const processed = await sharp(imageBuffer)\n .grayscale() // Convert to grayscale\n .normalize() // Normalize contrast\n .sharpen() // Sharpen text\n .toBuffer();\n\n return processed;\n } catch (error) {\n logger.warn(\n \"[RealOCR] Image preprocessing failed, using original:\",\n error,\n );\n return imageBuffer;\n }\n }\n\n private convertTesseractResult(result: Tesseract.RecognizeResult): OCRResult {\n const blocks: OCRResult[\"blocks\"] = [];\n\n // Process lines as blocks - Tesseract result.data has lines property\n interface TesseractLine {\n text: string;\n confidence: number;\n bbox: { x0: number; y0: number; x1: number; y1: number };\n words: Array<{\n text: string;\n confidence: number;\n bbox: { x0: number; y0: number; x1: number; y1: number };\n }>;\n }\n const data = result.data as { lines?: TesseractLine[]; text: string };\n const lines = data.lines || [];\n for (const line of lines) {\n if (line.confidence > 30) {\n // Filter low confidence\n blocks.push({\n text: line.text.trim(),\n bbox: {\n x: line.bbox.x0,\n y: line.bbox.y0,\n width: line.bbox.x1 - line.bbox.x0,\n height: line.bbox.y1 - line.bbox.y0,\n },\n confidence: line.confidence / 100,\n words: line.words.map((word) => ({\n text: word.text,\n bbox: {\n x: word.bbox.x0,\n y: word.bbox.y0,\n width: word.bbox.x1 - word.bbox.x0,\n height: word.bbox.y1 - word.bbox.y0,\n },\n confidence: word.confidence / 100,\n })),\n });\n }\n }\n\n const fullText = result.data.text.trim();\n\n return {\n text: fullText,\n blocks,\n fullText,\n };\n }\n\n async extractStructuredData(imageBuffer: Buffer): Promise<{\n tables?: Array<{ rows: string[][]; bbox: BoundingBox }>;\n forms?: Array<{ label: string; value: string; bbox: BoundingBox }>;\n lists?: Array<{ items: string[]; bbox: BoundingBox }>;\n }> {\n const ocrResult = await this.extractText(imageBuffer);\n\n return {\n tables: this.detectTables(ocrResult),\n forms: this.detectForms(ocrResult),\n lists: this.detectLists(ocrResult),\n };\n }\n\n private detectTables(\n ocrResult: OCRResult,\n ): Array<{ rows: string[][]; bbox: BoundingBox }> {\n const tables: Array<{ rows: string[][]; bbox: BoundingBox }> = [];\n\n // Group blocks by vertical alignment to detect table rows\n const rows: Map<number, typeof ocrResult.blocks> = new Map();\n\n for (const block of ocrResult.blocks) {\n // Round Y position to group nearby blocks\n const rowY = Math.round(block.bbox.y / 20) * 20;\n\n if (!rows.has(rowY)) {\n rows.set(rowY, []);\n }\n rows.get(rowY)?.push(block);\n }\n\n // Find potential tables (multiple aligned rows)\n const sortedRows = Array.from(rows.entries()).sort((a, b) => a[0] - b[0]);\n\n let tableRows: string[][] = [];\n let tableBounds: BoundingBox | null = null;\n\n for (const [y, rowBlocks] of sortedRows) {\n if (rowBlocks.length > 1) {\n // Sort blocks by X position\n rowBlocks.sort((a, b) => a.bbox.x - b.bbox.x);\n\n const rowTexts = rowBlocks.map((b) => b.text);\n tableRows.push(rowTexts);\n\n // Update table bounds\n if (!tableBounds) {\n tableBounds = { ...rowBlocks[0].bbox };\n } else {\n tableBounds.x = Math.min(tableBounds.x, rowBlocks[0].bbox.x);\n tableBounds.width =\n Math.max(...rowBlocks.map((b) => b.bbox.x + b.bbox.width)) -\n tableBounds.x;\n tableBounds.height = y + rowBlocks[0].bbox.height - tableBounds.y;\n }\n } else if (tableRows.length > 1 && tableBounds) {\n // End of table\n tables.push({\n rows: [...tableRows],\n bbox: { ...tableBounds },\n });\n tableRows = [];\n tableBounds = null;\n }\n }\n\n // Add final table if exists\n if (tableRows.length > 1 && tableBounds) {\n tables.push({\n rows: tableRows,\n bbox: tableBounds,\n });\n }\n\n return tables;\n }\n\n private detectForms(\n ocrResult: OCRResult,\n ): Array<{ label: string; value: string; bbox: BoundingBox }> {\n const forms: Array<{ label: string; value: string; bbox: BoundingBox }> =\n [];\n\n // Look for label-value patterns\n const blocks = ocrResult.blocks;\n\n for (let i = 0; i < blocks.length; i++) {\n const current = blocks[i];\n\n // Check if this looks like a label\n if (current.text.match(/[::]\\s*$/)) {\n const label = current.text.replace(/[::]\\s*$/, \"\").trim();\n\n // Look for value in nearby blocks\n for (let j = i + 1; j < blocks.length && j < i + 3; j++) {\n const next = blocks[j];\n\n // Check if horizontally aligned or just below\n const isAligned = Math.abs(current.bbox.y - next.bbox.y) < 10;\n const isBelow =\n next.bbox.y > current.bbox.y &&\n next.bbox.y < current.bbox.y + current.bbox.height + 30;\n\n if (isAligned || isBelow) {\n forms.push({\n label,\n value: next.text.trim(),\n bbox: {\n x: Math.min(current.bbox.x, next.bbox.x),\n y: current.bbox.y,\n width:\n Math.max(\n current.bbox.x + current.bbox.width,\n next.bbox.x + next.bbox.width,\n ) - Math.min(current.bbox.x, next.bbox.x),\n height: next.bbox.y + next.bbox.height - current.bbox.y,\n },\n });\n break;\n }\n }\n }\n }\n\n return forms;\n }\n\n private detectLists(\n ocrResult: OCRResult,\n ): Array<{ items: string[]; bbox: BoundingBox }> {\n const lists: Array<{ items: string[]; bbox: BoundingBox }> = [];\n\n let currentList: string[] = [];\n let listBounds: BoundingBox | null = null;\n\n for (const block of ocrResult.blocks) {\n // Check for list markers\n const listMatch = block.text.match(\n /^[\\u2022\\u2023\\u25E6\\u2043\\u2219•·‣⁃◦▪▫◆◇○●\\-*]\\s+(.+)$/,\n );\n const numberedMatch = block.text.match(\n /^(\\d+\\.|\\d+\\)|\\(\\d+\\)|[a-zA-Z]\\.)\\s+(.+)$/,\n );\n\n if (listMatch || numberedMatch) {\n const itemText = listMatch ? listMatch[1] : numberedMatch?.[2];\n currentList.push(itemText.trim());\n\n if (!listBounds) {\n listBounds = { ...block.bbox };\n } else {\n listBounds.width = Math.max(\n listBounds.width,\n block.bbox.x + block.bbox.width - listBounds.x,\n );\n listBounds.height = block.bbox.y + block.bbox.height - listBounds.y;\n }\n } else if (currentList.length > 0 && listBounds) {\n // End of list\n lists.push({\n items: [...currentList],\n bbox: { ...listBounds },\n });\n currentList = [];\n listBounds = null;\n }\n }\n\n // Add final list if exists\n if (currentList.length > 0 && listBounds) {\n lists.push({\n items: currentList,\n bbox: listBounds,\n });\n }\n\n return lists;\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n async dispose(): Promise<void> {\n if (this.worker) {\n await this.worker.terminate();\n this.worker = null;\n }\n this.initialized = false;\n this.initPromise = null;\n logger.info(\"[RealOCR] Disposed\");\n }\n}\n",
18
+ "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 { logger } from \"@elizaos/core\";\nimport sharp from \"sharp\";\nimport type { ScreenCapture, ScreenTile, VisionConfig } from \"./types\";\n\nconst execAsync = promisify(exec);\n\nexport class ScreenCaptureService {\n private config: VisionConfig;\n private activeTileIndex = 0;\n private lastCapture: ScreenCapture | null = null;\n\n constructor(config: VisionConfig) {\n this.config = config;\n }\n\n async getScreenInfo(): Promise<{ width: number; height: number } | null> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // macOS: Use system_profiler\n const { stdout } = await execAsync(\n \"system_profiler SPDisplaysDataType -json\",\n );\n const data = JSON.parse(stdout);\n\n if (data.SPDisplaysDataType?.[0]) {\n const display = data.SPDisplaysDataType[0];\n const resolution = display._items?.[0]?.native_resolution;\n if (resolution) {\n const match = resolution.match(/(\\d+) x (\\d+)/);\n if (match) {\n return {\n width: parseInt(match[1], 10),\n height: parseInt(match[2], 10),\n };\n }\n }\n }\n } else if (platform === \"linux\") {\n // Linux: Use xrandr\n const { stdout } = await execAsync(\n 'xrandr | grep \" connected primary\"',\n );\n const match = stdout.match(/(\\d+)x(\\d+)/);\n if (match) {\n return {\n width: parseInt(match[1], 10),\n height: parseInt(match[2], 10),\n };\n }\n } else if (platform === \"win32\") {\n // Windows: Use wmic\n const { stdout } = await execAsync(\n \"wmic path Win32_VideoController get CurrentHorizontalResolution,CurrentVerticalResolution /value\",\n );\n const width = stdout.match(/CurrentHorizontalResolution=(\\d+)/)?.[1];\n const height = stdout.match(/CurrentVerticalResolution=(\\d+)/)?.[1];\n if (width && height) {\n return {\n width: parseInt(width, 10),\n height: parseInt(height, 10),\n };\n }\n }\n } catch (error) {\n logger.error(\"[ScreenCapture] Failed to get screen info:\", error);\n }\n\n // Default fallback\n return { width: 1920, height: 1080 };\n }\n\n async captureScreen(): Promise<ScreenCapture> {\n const tempFile = path.join(process.cwd(), `temp_screen_${Date.now()}.png`);\n\n try {\n // Capture the screen\n await this.captureScreenToFile(tempFile);\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 || 1920;\n const height = metadata.height || 1080;\n\n // Create tiles\n const tileSize = this.config.tileSize || 256;\n const tiles: ScreenTile[] = [];\n\n for (let row = 0; row < Math.ceil(height / tileSize); row++) {\n for (let col = 0; col < Math.ceil(width / tileSize); col++) {\n const x = col * tileSize;\n const y = row * tileSize;\n const tileWidth = Math.min(tileSize, width - x);\n const tileHeight = Math.min(tileSize, height - y);\n\n tiles.push({\n id: `tile-${row}-${col}`,\n row,\n col,\n x,\n y,\n width: tileWidth,\n height: tileHeight,\n });\n }\n }\n\n // Process active tile based on order\n if (this.config.tileProcessingOrder === \"priority\") {\n // Focus on center tiles first\n const centerRow = Math.floor(\n tiles.length / 2 / Math.ceil(width / tileSize),\n );\n const centerCol = Math.floor(\n (tiles.length / 2) % Math.ceil(width / tileSize),\n );\n this.activeTileIndex =\n centerRow * Math.ceil(width / tileSize) + centerCol;\n } else if (this.config.tileProcessingOrder === \"random\") {\n this.activeTileIndex = Math.floor(Math.random() * tiles.length);\n } else {\n // Sequential\n this.activeTileIndex = (this.activeTileIndex + 1) % tiles.length;\n }\n\n // Extract active tile data\n const activeTile = tiles[this.activeTileIndex];\n if (activeTile) {\n try {\n const tileBuffer = await image\n .extract({\n left: activeTile.x,\n top: activeTile.y,\n width: activeTile.width,\n height: activeTile.height,\n })\n .png()\n .toBuffer();\n\n activeTile.data = tileBuffer;\n } catch (error) {\n logger.error(\"[ScreenCapture] Failed to extract tile:\", error);\n }\n }\n\n // Clean up temp file\n await fs.unlink(tempFile).catch(() => {});\n\n // Create screen capture object\n const capture: ScreenCapture = {\n timestamp: Date.now(),\n width,\n height,\n data: imageBuffer,\n tiles,\n };\n\n this.lastCapture = capture;\n return capture;\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): Promise<void> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // macOS: Use screencapture\n await execAsync(`screencapture -x \"${outputPath}\"`);\n } else if (platform === \"linux\") {\n // Linux: Use scrot or gnome-screenshot\n try {\n await execAsync(`scrot \"${outputPath}\"`);\n } catch (_error) {\n // Fallback to gnome-screenshot\n await execAsync(`gnome-screenshot -f \"${outputPath}\"`);\n }\n } else if (platform === \"win32\") {\n // Windows: Use PowerShell\n const script = `\n Add-Type -AssemblyName System.Windows.Forms;\n Add-Type -AssemblyName System.Drawing;\n $screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds;\n $bitmap = New-Object System.Drawing.Bitmap $screen.Width, $screen.Height;\n $graphics = [System.Drawing.Graphics]::FromImage($bitmap);\n $graphics.CopyFromScreen($screen.Location, [System.Drawing.Point]::Empty, $screen.Size);\n $bitmap.Save('${outputPath.replace(/\\\\/g, \"\\\\\\\\\")}');\n $graphics.Dispose();\n $bitmap.Dispose();\n `;\n await execAsync(`powershell -Command \"${script.replace(/\\n/g, \" \")}\"`);\n } else {\n throw new Error(`Unsupported platform: ${platform}`);\n }\n } catch (error) {\n logger.error(\"[ScreenCapture] Screen capture failed:\", error);\n\n // Provide helpful error messages\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n if (platform === \"linux\" && errorMessage.includes(\"command not found\")) {\n throw new Error(\n \"Screen capture tool not found. Install with: sudo apt-get install scrot\",\n );\n }\n throw error;\n }\n }\n\n getActiveTile(): ScreenTile | null {\n if (!this.lastCapture || !this.lastCapture.tiles[this.activeTileIndex]) {\n return null;\n }\n return this.lastCapture.tiles[this.activeTileIndex];\n }\n\n getAllTiles(): ScreenTile[] {\n return this.lastCapture?.tiles || [];\n }\n\n getProcessedTiles(): ScreenTile[] {\n return this.lastCapture?.tiles.filter((t) => t.analysis) || [];\n }\n}\n",
19
+ "/**\n * Test-input shim for plugin-vision.\n *\n * Lets tests inject a fixture image into the vision analysis pipeline\n * without monkey-patching platform capture code.\n *\n * Selection: read `ELIZA_VISION_TEST_INPUT`:\n * - \"image\" → return the fixture bytes (resolved via\n * `ELIZA_VISION_TEST_FIXTURE` env var, default the bundled\n * test/fixtures/sample-scene.png path).\n * - \"camera\" / \"screen\" / unset → return null, signaling that the caller\n * should use the existing platform capture path.\n *\n * Single-purpose helper: anything that wants test-injected pixels reads\n * `getTestImage()`. When it returns a Buffer, use those bytes. When it\n * returns null, fall through to live capture.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { logger } from \"@elizaos/core\";\n\nexport type TestInputMode = \"image\" | \"camera\" | \"screen\" | \"unset\";\n\nexport function getTestInputMode(): TestInputMode {\n const raw = (process.env.ELIZA_VISION_TEST_INPUT ?? \"\").trim().toLowerCase();\n if (raw === \"image\") return \"image\";\n if (raw === \"camera\") return \"camera\";\n if (raw === \"screen\") return \"screen\";\n return \"unset\";\n}\n\nconst FIXTURE_DEFAULT_REL = \"test/fixtures/sample-scene.png\";\n\nfunction resolveFixturePath(): string {\n const fromEnv = process.env.ELIZA_VISION_TEST_FIXTURE;\n if (fromEnv) return resolve(fromEnv);\n // Resolve relative to the package root (parent of `src` / `dist`).\n return resolve(process.cwd(), FIXTURE_DEFAULT_REL);\n}\n\nlet cached: Buffer | null = null;\nlet cachedKey: string | null = null;\n\n/**\n * If `ELIZA_VISION_TEST_INPUT=image`, return fixture bytes (PNG buffer);\n * otherwise return null. Result is cached per-fixture-path for the process.\n */\nexport function getTestImage(): Buffer | null {\n if (getTestInputMode() !== \"image\") return null;\n const path = resolveFixturePath();\n if (cachedKey === path && cached) return cached;\n if (!existsSync(path)) {\n logger.warn(\n `[plugin-vision] ELIZA_VISION_TEST_INPUT=image set but fixture not found at ${path}.`,\n );\n return null;\n }\n cached = readFileSync(path);\n cachedKey = path;\n return cached;\n}\n",
20
+ "// Vision models for object detection and pose estimation\n\nimport { logger } from \"@elizaos/core\";\nimport type { DetectedObject, PersonInfo } from \"./types\";\n\n// Lazy-loaded TensorFlow.js modules — the native addon may not be available\n// (e.g. when installed via bun or on platforms without prebuilt binaries).\n// We load them on first use so the rest of the plugin still works.\nlet tf: typeof import(\"@tensorflow/tfjs-node\") | null = null;\nlet cocoSsd: typeof import(\"@tensorflow-models/coco-ssd\") | null = null;\nlet poseDetection: typeof import(\"@tensorflow-models/pose-detection\") | null =\n null;\n\nasync function loadTfModules(): Promise<boolean> {\n if (tf) return true;\n try {\n tf = await import(\"@tensorflow/tfjs-node\");\n cocoSsd = await import(\"@tensorflow-models/coco-ssd\");\n poseDetection = await import(\"@tensorflow-models/pose-detection\");\n return true;\n } catch (err) {\n logger.warn(\n \"[VisionModels] TensorFlow.js native addon not available — \" +\n \"falling back to description-based detection. \" +\n \"Run `npm rebuild @tensorflow/tfjs-node --build-addon-from-source` to enable hardware-accelerated vision.\",\n );\n return false;\n }\n}\n\n// Define types that are missing from types.ts\nexport interface VisionModelConfig {\n enableObjectDetection?: boolean;\n enablePoseDetection?: boolean;\n florence2?: {\n baseUrl: string;\n apiKey?: string;\n };\n vlm?: {\n model: string;\n temperature: number;\n maxTokens: number;\n };\n}\n\nexport type Pose = \"sitting\" | \"standing\" | \"lying\" | \"walking\" | \"unknown\";\n\nexport interface PoseLandmark {\n name: string;\n x: number;\n y: number;\n score: number;\n}\n\nexport class VisionModels {\n private objectDetectionModel: Awaited<\n ReturnType<NonNullable<typeof cocoSsd>[\"load\"]>\n > | null = null;\n private poseDetector: Awaited<\n ReturnType<NonNullable<typeof poseDetection>[\"createDetector\"]>\n > | null = null;\n private initialized = false;\n private tfAvailable = false;\n\n async initialize(config: VisionModelConfig): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n logger.info(\"[VisionModels] Initializing vision models...\");\n\n this.tfAvailable = await loadTfModules();\n\n if (!this.tfAvailable || !tf || !cocoSsd || !poseDetection) {\n // Mark as initialized so we use the fallback paths instead of retrying.\n this.initialized = true;\n logger.info(\n \"[VisionModels] Initialized without TensorFlow (fallback mode)\",\n );\n return;\n }\n\n try {\n // Initialize TensorFlow.js backend\n await tf.ready();\n logger.info(\"[VisionModels] TensorFlow.js backend ready\");\n\n // Load object detection model\n if (config.enableObjectDetection) {\n try {\n logger.info(\"[VisionModels] Loading COCO-SSD model...\");\n this.objectDetectionModel = await cocoSsd.load({\n base: \"mobilenet_v2\",\n });\n logger.info(\"[VisionModels] COCO-SSD model loaded\");\n } catch (error) {\n logger.error(\"[VisionModels] Failed to load COCO-SSD model:\", error);\n }\n }\n\n // Load pose detection model\n if (config.enablePoseDetection) {\n try {\n logger.info(\"[VisionModels] Loading PoseNet model...\");\n const detectorConfig = {\n architecture: \"MobileNetV1\" as const,\n outputStride: 16 as const,\n inputResolution: { width: 640, height: 480 },\n multiplier: 0.75 as const,\n };\n\n this.poseDetector = await poseDetection.createDetector(\n poseDetection.SupportedModels.PoseNet,\n detectorConfig,\n );\n logger.info(\"[VisionModels] PoseNet model loaded\");\n } catch (error) {\n logger.error(\"[VisionModels] Failed to load PoseNet model:\", error);\n }\n }\n\n this.initialized = true;\n logger.info(\"[VisionModels] Vision models initialized\");\n } catch (error) {\n logger.error(\"[VisionModels] Initialization failed:\", error);\n throw error;\n }\n }\n\n hasObjectDetection(): boolean {\n return this.objectDetectionModel !== null;\n }\n\n hasPoseDetection(): boolean {\n return this.poseDetector !== null;\n }\n\n async detectObjects(\n imageData: Buffer,\n _width: number,\n _height: number,\n description?: string,\n ): Promise<DetectedObject[]> {\n if (!this.objectDetectionModel || !tf) {\n logger.warn(\"[VisionModels] Object detection model not loaded\");\n return this.enhancedObjectDetection(description);\n }\n\n try {\n // Convert image data to tensor\n const imageTensor = tf.node.decodeImage(imageData, 3);\n\n // Ensure the tensor has the right shape [1, height, width, 3]\n const batched = imageTensor.expandDims(0);\n\n // Run detection - cocoSsd.detect expects specific input types\n // We squeeze the batch dimension back for detection\n const squeezed = batched.squeeze([0]) as ReturnType<\n typeof imageTensor.expandDims\n > extends infer T\n ? T\n : never;\n const predictions = await this.objectDetectionModel.detect(\n squeezed as Parameters<typeof this.objectDetectionModel.detect>[0],\n );\n squeezed.dispose();\n\n // Clean up tensors\n imageTensor.dispose();\n batched.dispose();\n\n // Convert predictions to our format\n const objects: DetectedObject[] = predictions.map((pred, idx) => ({\n id: `obj-${Date.now()}-${idx}`,\n type: pred.class,\n confidence: pred.score,\n boundingBox: {\n x: pred.bbox[0],\n y: pred.bbox[1],\n width: pred.bbox[2],\n height: pred.bbox[3],\n },\n }));\n\n logger.debug(`[VisionModels] Detected ${objects.length} objects`);\n return objects;\n } catch (error) {\n logger.error(\"[VisionModels] Object detection failed:\", error);\n return this.enhancedObjectDetection(description);\n }\n }\n\n private enhancedObjectDetection(description?: string): DetectedObject[] {\n // Enhanced object detection based on scene description\n if (!description) {\n return [];\n }\n\n const objects: DetectedObject[] = [];\n\n // Extract objects from description using patterns\n const objectPatterns = [\n {\n pattern:\n /(\\d+)?\\s*(person|people|man|men|woman|women|child|children)/gi,\n type: \"person\",\n },\n {\n pattern: /(\\d+)?\\s*(laptop|computer|monitor|screen|display)/gi,\n type: \"laptop\",\n },\n { pattern: /(\\d+)?\\s*(phone|smartphone|mobile)/gi, type: \"cell phone\" },\n { pattern: /(\\d+)?\\s*(book|notebook|journal)/gi, type: \"book\" },\n { pattern: /(\\d+)?\\s*(cup|mug|glass|bottle)/gi, type: \"cup\" },\n { pattern: /(\\d+)?\\s*(chair|seat|sofa|couch)/gi, type: \"chair\" },\n { pattern: /(\\d+)?\\s*(table|desk)/gi, type: \"dining table\" },\n { pattern: /(\\d+)?\\s*(car|vehicle|truck|bus)/gi, type: \"car\" },\n { pattern: /(\\d+)?\\s*(dog|cat|pet|animal)/gi, type: \"animal\" },\n { pattern: /(\\d+)?\\s*(plant|tree|flower)/gi, type: \"potted plant\" },\n ];\n\n for (const { pattern, type } of objectPatterns) {\n const matches = Array.from(description.matchAll(pattern));\n for (const match of matches) {\n const count = match[1] ? parseInt(match[1], 10) : 1;\n for (let i = 0; i < count; i++) {\n objects.push({\n id: `obj-${type}-${Date.now()}-${i}`,\n type,\n confidence: 0.85, // High confidence since it's from VLM\n boundingBox: this.generatePlausibleBoundingBox(type, i, count),\n });\n }\n }\n }\n\n return objects;\n }\n\n private generatePlausibleBoundingBox(\n type: string,\n index: number,\n total: number,\n ): {\n x: number;\n y: number;\n width: number;\n height: number;\n } {\n // Generate plausible bounding boxes based on object type and position\n const basePositions: Record<\n string,\n { width: number; height: number; y: number }\n > = {\n person: { width: 150, height: 300, y: 100 },\n laptop: { width: 200, height: 150, y: 250 },\n \"cell phone\": { width: 50, height: 100, y: 300 },\n book: { width: 100, height: 150, y: 280 },\n cup: { width: 60, height: 80, y: 300 },\n chair: { width: 180, height: 200, y: 200 },\n \"dining table\": { width: 400, height: 200, y: 250 },\n car: { width: 300, height: 200, y: 150 },\n animal: { width: 120, height: 100, y: 300 },\n \"potted plant\": { width: 100, height: 150, y: 200 },\n };\n\n const base = basePositions[type] || { width: 100, height: 100, y: 200 };\n const spacing = 640 / (total + 1); // Distribute across frame width\n\n return {\n x: spacing * (index + 1) - base.width / 2,\n y: base.y + (Math.random() - 0.5) * 50,\n width: base.width + (Math.random() - 0.5) * 40,\n height: base.height + (Math.random() - 0.5) * 40,\n };\n }\n\n async detectPoses(\n imageData: Buffer,\n width: number,\n height: number,\n description?: string,\n ): Promise<PersonInfo[]> {\n if (!this.poseDetector || !tf) {\n logger.warn(\"[VisionModels] Pose detection model not loaded\");\n return this.enhancedPoseDetection(description);\n }\n\n try {\n // Convert image data to tensor\n const imageTensor = tf.node.decodeImage(imageData, 3);\n\n // Run pose detection - estimatePoses expects ImageData-like object\n const poses = await this.poseDetector.estimatePoses({\n data: new Uint8ClampedArray(imageTensor.dataSync()),\n width,\n height,\n } as ImageData);\n\n // Clean up tensor\n imageTensor.dispose();\n\n // Convert poses to PersonInfo\n return this.convertPosesToPersonInfo(poses);\n } catch (error) {\n logger.error(\"[VisionModels] Pose detection failed:\", error);\n return this.enhancedPoseDetection(description);\n }\n }\n\n private enhancedPoseDetection(description?: string): PersonInfo[] {\n // Enhanced pose detection based on scene description\n if (!description) {\n return [];\n }\n\n const people: PersonInfo[] = [];\n const descLower = description.toLowerCase();\n\n // Extract people count and descriptions\n const peopleMatch = description.match(\n /(\\d+)?\\s*(person|people|man|men|woman|women|child|children)/gi,\n );\n if (!peopleMatch) {\n return [];\n }\n\n const count = peopleMatch[0].match(/\\d+/)?.[0]\n ? parseInt(peopleMatch[0].match(/\\d+/)?.[0], 10)\n : 1;\n\n // Analyze description for pose and facing information\n const poseKeywords = {\n standing: [\"standing\", \"stand\", \"upright\"],\n sitting: [\"sitting\", \"seated\", \"sit\", \"chair\"],\n walking: [\"walking\", \"walk\", \"moving\"],\n lying: [\"lying\", \"laying\", \"reclined\"],\n };\n\n const facingKeywords = {\n camera: [\n \"facing camera\",\n \"looking at camera\",\n \"facing forward\",\n \"front view\",\n ],\n away: [\"back to camera\", \"facing away\", \"back view\"],\n left: [\"facing left\", \"profile left\", \"left side\"],\n right: [\"facing right\", \"profile right\", \"right side\"],\n };\n\n let detectedPose = \"standing\";\n let detectedFacing = \"camera\";\n\n // Detect pose\n for (const [pose, keywords] of Object.entries(poseKeywords)) {\n if (keywords.some((kw) => descLower.includes(kw))) {\n detectedPose = pose;\n break;\n }\n }\n\n // Detect facing\n for (const [facing, keywords] of Object.entries(facingKeywords)) {\n if (keywords.some((kw) => descLower.includes(kw))) {\n detectedFacing = facing;\n break;\n }\n }\n\n // Create PersonInfo for each detected person\n for (let i = 0; i < count; i++) {\n const boundingBox = this.generatePlausibleBoundingBox(\"person\", i, count);\n\n people.push({\n id: `person-${Date.now()}-${i}`,\n boundingBox,\n pose: detectedPose as \"sitting\" | \"standing\" | \"lying\" | \"unknown\",\n facing: detectedFacing as \"camera\" | \"away\" | \"left\" | \"right\",\n confidence: 0.85,\n keypoints: this.generatePlausibleKeypoints(\n boundingBox,\n detectedPose as Pose,\n detectedFacing,\n ).map((kp) => ({\n part: kp.name,\n position: { x: kp.x, y: kp.y },\n score: kp.score,\n })),\n });\n }\n\n return people;\n }\n\n private generatePlausibleKeypoints(\n boundingBox: { x: number; y: number; width: number; height: number },\n pose: Pose,\n _facing: string,\n ): PoseLandmark[] {\n // Generate plausible keypoints based on pose and facing\n const { x, y, width, height } = boundingBox;\n const centerX = x + width / 2;\n\n const keypoints: PoseLandmark[] = [];\n\n // Basic keypoint positions relative to bounding box\n const positions = {\n nose: { x: centerX, y: y + height * 0.1 },\n leftEye: { x: centerX - width * 0.1, y: y + height * 0.08 },\n rightEye: { x: centerX + width * 0.1, y: y + height * 0.08 },\n leftEar: { x: centerX - width * 0.15, y: y + height * 0.1 },\n rightEar: { x: centerX + width * 0.15, y: y + height * 0.1 },\n leftShoulder: { x: centerX - width * 0.25, y: y + height * 0.25 },\n rightShoulder: { x: centerX + width * 0.25, y: y + height * 0.25 },\n leftElbow: { x: centerX - width * 0.3, y: y + height * 0.4 },\n rightElbow: { x: centerX + width * 0.3, y: y + height * 0.4 },\n leftWrist: { x: centerX - width * 0.25, y: y + height * 0.55 },\n rightWrist: { x: centerX + width * 0.25, y: y + height * 0.55 },\n leftHip: { x: centerX - width * 0.15, y: y + height * 0.5 },\n rightHip: { x: centerX + width * 0.15, y: y + height * 0.5 },\n leftKnee: { x: centerX - width * 0.15, y: y + height * 0.7 },\n rightKnee: { x: centerX + width * 0.15, y: y + height * 0.7 },\n leftAnkle: { x: centerX - width * 0.15, y: y + height * 0.9 },\n rightAnkle: { x: centerX + width * 0.15, y: y + height * 0.9 },\n };\n\n // Adjust positions based on pose\n if (pose === \"sitting\") {\n // Lower hips and knees for sitting pose\n positions.leftHip.y += height * 0.1;\n positions.rightHip.y += height * 0.1;\n positions.leftKnee.y -= height * 0.1;\n positions.rightKnee.y -= height * 0.1;\n }\n\n // Convert to PoseLandmark format\n Object.entries(positions).forEach(([name, pos]) => {\n keypoints.push({\n name: name as string,\n x: pos.x,\n y: pos.y,\n score: 0.85,\n });\n });\n\n return keypoints;\n }\n\n convertPosesToPersonInfo(\n poses: Array<{\n keypoints: Array<{ name?: string; x: number; y: number; score?: number }>;\n score?: number;\n }>,\n ): PersonInfo[] {\n return poses.map((pose, index) => {\n const keypoints = pose.keypoints;\n\n // Calculate bounding box from keypoints\n const xs = keypoints.map((kp) => kp.x);\n const ys = keypoints.map((kp) => kp.y);\n const minX = Math.min(...xs);\n const maxX = Math.max(...xs);\n const minY = Math.min(...ys);\n const maxY = Math.max(...ys);\n\n const boundingBox = {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY,\n };\n\n // Determine pose from keypoints\n const detectedPose = this.determinePoseFromKeypoints(keypoints);\n\n // Determine facing direction\n const facing = this.determineFacingDirection(keypoints);\n\n // Convert keypoints to our format\n const convertedKeypoints = keypoints.map((kp) => ({\n part: kp.name || \"unknown\",\n position: { x: kp.x, y: kp.y },\n score: kp.score || 0,\n }));\n\n return {\n id: `person-${Date.now()}-${index}`,\n boundingBox,\n pose: detectedPose as \"sitting\" | \"standing\" | \"lying\" | \"unknown\",\n facing,\n confidence: pose.score || 0.5,\n keypoints: convertedKeypoints,\n };\n });\n }\n\n private determinePoseFromKeypoints(\n keypoints: Array<{ name?: string; x: number; y: number; score?: number }>,\n ): Pose {\n // Simple heuristic to determine pose\n const leftHip = keypoints.find((kp) => kp.name === \"left_hip\");\n const rightHip = keypoints.find((kp) => kp.name === \"right_hip\");\n const leftKnee = keypoints.find((kp) => kp.name === \"left_knee\");\n const rightKnee = keypoints.find((kp) => kp.name === \"right_knee\");\n const leftShoulder = keypoints.find((kp) => kp.name === \"left_shoulder\");\n const rightShoulder = keypoints.find((kp) => kp.name === \"right_shoulder\");\n\n if (!leftHip || !rightHip || !leftKnee || !rightKnee) {\n return \"unknown\";\n }\n\n const hipY = (leftHip.y + rightHip.y) / 2;\n const kneeY = (leftKnee.y + rightKnee.y) / 2;\n const shoulderY =\n leftShoulder && rightShoulder\n ? (leftShoulder.y + rightShoulder.y) / 2\n : hipY - 100;\n\n // Check if person is lying down (shoulders and hips at similar height)\n if (Math.abs(shoulderY - hipY) < 50) {\n return \"lying\";\n }\n\n // Check if person is sitting (knees close to hips)\n if (Math.abs(hipY - kneeY) < 100) {\n return \"sitting\";\n }\n\n // Otherwise assume standing\n return \"standing\";\n }\n\n private determineFacingDirection(\n keypoints: Array<{ name?: string; x: number; y: number; score?: number }>,\n ): \"camera\" | \"away\" | \"left\" | \"right\" {\n const leftShoulder = keypoints.find((kp) => kp.name === \"left_shoulder\");\n const rightShoulder = keypoints.find((kp) => kp.name === \"right_shoulder\");\n const nose = keypoints.find((kp) => kp.name === \"nose\");\n\n if (!leftShoulder || !rightShoulder || !nose) {\n return \"camera\"; // Default\n }\n\n const shoulderWidth = Math.abs(rightShoulder.x - leftShoulder.x);\n const shoulderMidpoint = (leftShoulder.x + rightShoulder.x) / 2;\n const noseOffset = nose.x - shoulderMidpoint;\n\n // If shoulders are narrow, person is likely in profile\n if (shoulderWidth < 50) {\n return noseOffset > 0 ? \"right\" : \"left\";\n }\n\n // If nose is significantly offset from shoulder midpoint, person is turning\n if (Math.abs(noseOffset) > shoulderWidth * 0.3) {\n return noseOffset > 0 ? \"right\" : \"left\";\n }\n\n // Check if both ears are visible (facing camera) or not (facing away)\n const leftEar = keypoints.find((kp) => kp.name === \"left_ear\");\n const rightEar = keypoints.find((kp) => kp.name === \"right_ear\");\n\n if (leftEar && rightEar && leftEar.score && rightEar.score) {\n if (leftEar.score > 0.5 && rightEar.score > 0.5) {\n return \"camera\";\n }\n }\n\n return \"camera\"; // Default\n }\n\n async dispose(): Promise<void> {\n if (this.objectDetectionModel) {\n // COCO-SSD doesn't have a dispose method, but we can clear the reference\n this.objectDetectionModel = null;\n }\n\n if (this.poseDetector) {\n this.poseDetector.dispose();\n this.poseDetector = null;\n }\n\n this.initialized = false;\n logger.info(\"[VisionModels] Models disposed\");\n }\n}\n",
21
+ "import * as path from \"node:path\";\nimport { TextDecoder } from \"node:util\";\nimport { Worker } from \"node:worker_threads\";\nimport { logger } from \"@elizaos/core\";\nimport type {\n EnhancedSceneDescription,\n Florence2Result,\n OCRResult,\n ScreenCapture,\n VisionConfig,\n} from \"./types\";\n\ninterface WorkerStats {\n fps: number;\n frameCount: number;\n lastUpdate: number;\n}\n\nexport class VisionWorkerManager {\n private config: VisionConfig;\n\n // Workers\n private screenCaptureWorker: Worker | null = null;\n private florence2Worker: Worker | null = null;\n private ocrWorker: Worker | null = null;\n\n // Shared buffers\n private screenBuffer: SharedArrayBuffer;\n private florence2ResultsBuffer: SharedArrayBuffer;\n private ocrResultsBuffer: SharedArrayBuffer;\n\n // Buffer views\n private screenAtomicState: Int32Array;\n private florence2ResultsView: DataView;\n private ocrResultsView: DataView;\n\n // Buffer sizes\n private readonly SCREEN_BUFFER_SIZE = 50 * 1024 * 1024; // 50MB for 4K screen\n private readonly FLORENCE2_RESULTS_SIZE = 10 * 1024 * 1024; // 10MB for results\n private readonly OCR_RESULTS_SIZE = 5 * 1024 * 1024; // 5MB for OCR text\n\n // Atomic indices\n private readonly FRAME_ID_INDEX = 0;\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\n // Worker stats\n private workerStats = new Map<string, WorkerStats>();\n\n // Latest processed data cache\n private latestScreenCapture: ScreenCapture | null = null;\n private latestFlorence2Results = new Map<string, Florence2Result>();\n private latestOCRResult: OCRResult | null = null;\n private lastProcessedFrameId = -1;\n\n // Worker restart tracking\n private restartAttempts = new Map<string, number>();\n private readonly MAX_RESTART_ATTEMPTS = 3;\n\n constructor(config: VisionConfig) {\n this.config = config;\n\n // Initialize shared buffers\n this.screenBuffer = new SharedArrayBuffer(this.SCREEN_BUFFER_SIZE);\n this.florence2ResultsBuffer = new SharedArrayBuffer(\n this.FLORENCE2_RESULTS_SIZE,\n );\n this.ocrResultsBuffer = new SharedArrayBuffer(this.OCR_RESULTS_SIZE);\n\n // Create views\n this.screenAtomicState = new Int32Array(this.screenBuffer, 0, 6);\n this.florence2ResultsView = new DataView(this.florence2ResultsBuffer);\n this.ocrResultsView = new DataView(this.ocrResultsBuffer);\n }\n\n async initialize(): Promise<void> {\n logger.info(\"[VisionWorkerManager] Initializing worker threads...\");\n\n try {\n // Start screen capture worker\n await this.startScreenCaptureWorker();\n\n // Start Florence-2 worker if enabled\n if (this.config.florence2Enabled) {\n await this.startFlorence2Worker();\n }\n\n // Start OCR worker if enabled\n if (this.config.ocrEnabled) {\n await this.startOCRWorker();\n }\n\n logger.info(\"[VisionWorkerManager] All workers initialized\");\n } catch (error) {\n logger.error(\n \"[VisionWorkerManager] Failed to initialize workers:\",\n error,\n );\n throw error;\n }\n }\n\n private async startScreenCaptureWorker(): Promise<void> {\n const workerPath = path.join(\n __dirname,\n \"workers\",\n \"screen-capture-worker.js\",\n );\n\n this.screenCaptureWorker = new Worker(workerPath, {\n workerData: {\n config: {\n displayIndex: this.config.displayIndex,\n captureAllDisplays: this.config.captureAllDisplays,\n targetFPS: this.config.targetScreenFPS,\n sharedBufferSize: this.SCREEN_BUFFER_SIZE,\n },\n sharedBuffer: this.screenBuffer,\n },\n });\n\n this.screenCaptureWorker.on(\"message\", (msg) => {\n if (msg.type === \"fps\") {\n this.workerStats.set(\"screenCapture\", {\n fps: msg.fps,\n frameCount: msg.frameCount,\n lastUpdate: Date.now(),\n });\n } else if (msg.type === \"error\") {\n logger.error(\"[ScreenCaptureWorker] Error:\", msg.error);\n } else if (msg.type === \"log\") {\n // Handle worker log messages\n this.handleWorkerLog(\"ScreenCaptureWorker\", msg);\n }\n });\n\n this.screenCaptureWorker.on(\"error\", (error) => {\n logger.error(\n \"[ScreenCaptureWorker] Worker error:\",\n error instanceof Error ? error.message : String(error),\n );\n // Attempt to restart worker after error\n setTimeout(() => this.restartScreenCaptureWorker(), 1000);\n });\n\n this.screenCaptureWorker.on(\"exit\", (code) => {\n if (code !== 0) {\n logger.error(\n `[ScreenCaptureWorker] Worker stopped with exit code ${code}`,\n );\n // Attempt to restart worker after crash\n setTimeout(() => this.restartScreenCaptureWorker(), 1000);\n }\n });\n }\n\n private async startFlorence2Worker(): Promise<void> {\n const workerPath = path.join(__dirname, \"workers\", \"florence2-worker.js\");\n\n // Calculate priority tiles (center tiles)\n const priorityTiles: number[] = [];\n const tileSize = this.config.tileSize || 256;\n const estimatedCols = Math.ceil(1920 / tileSize); // Estimate based on common resolution\n const centerRow = Math.floor(estimatedCols / 2);\n const centerCol = Math.floor(estimatedCols / 2);\n\n // Add center and adjacent tiles as priority\n for (let r = centerRow - 1; r <= centerRow + 1; r++) {\n for (let c = centerCol - 1; c <= centerCol + 1; c++) {\n if (r >= 0 && c >= 0) {\n priorityTiles.push(r * estimatedCols + c);\n }\n }\n }\n\n this.florence2Worker = new Worker(workerPath, {\n workerData: {\n config: {\n tileSize: this.config.tileSize || 256,\n priorityTiles,\n },\n sharedBuffer: this.screenBuffer,\n resultsBuffer: this.florence2ResultsBuffer,\n },\n });\n\n this.florence2Worker.on(\"message\", (msg) => {\n if (msg.type === \"fps\") {\n this.workerStats.set(\"florence2\", {\n fps: msg.fps,\n frameCount: msg.frameCount,\n lastUpdate: Date.now(),\n });\n } else if (msg.type === \"tile_analyzed\") {\n // Update latest results cache\n this.updateFlorence2Cache(msg);\n } else if (msg.type === \"error\") {\n logger.error(\"[Florence2Worker] Error:\", msg.error);\n } else if (msg.type === \"log\") {\n // Handle worker log messages\n this.handleWorkerLog(\"Florence2Worker\", msg);\n }\n });\n\n this.florence2Worker.on(\"error\", (error) => {\n logger.error(\n \"[Florence2Worker] Worker error:\",\n error instanceof Error ? error.message : String(error),\n );\n // Attempt to restart worker after error\n setTimeout(() => this.restartFlorence2Worker(), 1000);\n });\n\n this.florence2Worker.on(\"exit\", (code) => {\n if (code !== 0) {\n logger.error(`[Florence2Worker] Worker stopped with exit code ${code}`);\n // Attempt to restart worker after crash\n setTimeout(() => this.restartFlorence2Worker(), 1000);\n }\n });\n }\n\n private async startOCRWorker(): Promise<void> {\n const workerPath = path.join(__dirname, \"workers\", \"ocr-worker.js\");\n\n this.ocrWorker = new Worker(workerPath, {\n workerData: {\n config: {\n processFullScreen: true,\n tileSize: this.config.tileSize || 256,\n textRegions: this.config.textRegions,\n },\n sharedBuffer: this.screenBuffer,\n resultsBuffer: this.ocrResultsBuffer,\n },\n });\n\n this.ocrWorker.on(\"message\", (msg) => {\n if (msg.type === \"fps\") {\n this.workerStats.set(\"ocr\", {\n fps: msg.fps,\n frameCount: msg.frameCount,\n lastUpdate: Date.now(),\n });\n } else if (msg.type === \"ocr_complete\") {\n // Update latest OCR cache\n this.updateOCRCache(msg);\n } else if (msg.type === \"error\") {\n logger.error(\"[OCRWorker] Error:\", msg.error);\n } else if (msg.type === \"log\") {\n // Handle worker log messages\n this.handleWorkerLog(\"OCRWorker\", msg);\n }\n });\n\n this.ocrWorker.on(\"error\", (error) => {\n logger.error(\n \"[OCRWorker] Worker error:\",\n error instanceof Error ? error.message : String(error),\n );\n // Attempt to restart worker after error\n setTimeout(() => this.restartOCRWorker(), 1000);\n });\n\n this.ocrWorker.on(\"exit\", (code) => {\n if (code !== 0) {\n logger.error(`[OCRWorker] Worker stopped with exit code ${code}`);\n // Attempt to restart worker after crash\n setTimeout(() => this.restartOCRWorker(), 1000);\n }\n });\n }\n\n private updateFlorence2Cache(msg: { tileId: string }): void {\n // Read result from shared buffer\n try {\n const tileId = msg.tileId;\n const result = this.readFlorence2Result(tileId);\n if (result) {\n this.latestFlorence2Results.set(tileId, result);\n }\n } catch (error) {\n logger.error(\n \"[VisionWorkerManager] Failed to update Florence2 cache:\",\n error,\n );\n }\n }\n\n private updateOCRCache(_msg: unknown): void {\n // Read OCR result from shared buffer\n try {\n const result = this.readOCRResult();\n if (result) {\n this.latestOCRResult = result;\n }\n } catch (error) {\n logger.error(\"[VisionWorkerManager] Failed to update OCR cache:\", error);\n }\n }\n\n private readFlorence2Result(tileId: string): Florence2Result | null {\n try {\n // Calculate tile index from ID\n const match = tileId.match(/tile-(\\d+)-(\\d+)/);\n if (!match) {\n return null;\n }\n\n const row = parseInt(match[1], 10);\n const col = parseInt(match[2], 10);\n const tileIndex = row * 10 + col; // Assuming max 10 columns\n\n const RESULTS_HEADER_SIZE = 16;\n const MAX_RESULT_SIZE = 4096;\n const offset = RESULTS_HEADER_SIZE + tileIndex * MAX_RESULT_SIZE;\n\n // Read length\n const length = this.florence2ResultsView.getUint32(offset, true);\n if (length === 0 || length > MAX_RESULT_SIZE - 4) {\n return null;\n }\n\n // Read JSON data\n const bytes = new Uint8Array(length);\n for (let i = 0; i < length; i++) {\n bytes[i] = this.florence2ResultsView.getUint8(offset + 4 + i);\n }\n\n const json = new TextDecoder().decode(bytes);\n return JSON.parse(json);\n } catch (error) {\n logger.error(\n \"[VisionWorkerManager] Failed to read Florence2 result:\",\n error,\n );\n return null;\n }\n }\n\n private readOCRResult(): OCRResult | null {\n try {\n const RESULTS_HEADER_SIZE = 16;\n const offset = RESULTS_HEADER_SIZE;\n\n // Read length\n const length = this.ocrResultsView.getUint32(offset, true);\n if (length === 0) {\n return null;\n }\n\n // Read frame ID and timestamp\n const _frameId = this.ocrResultsView.getUint32(offset + 4, true);\n const _timestamp = this.ocrResultsView.getFloat64(offset + 8, true);\n\n // Read JSON data\n const dataOffset = offset + 16;\n const bytes = new Uint8Array(Math.min(length, 65536));\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = this.ocrResultsView.getUint8(dataOffset + i);\n }\n\n const json = new TextDecoder().decode(bytes);\n return JSON.parse(json);\n } catch (error) {\n logger.error(\"[VisionWorkerManager] Failed to read OCR result:\", error);\n return null;\n }\n }\n\n // Public API - Non-blocking access to latest data\n\n getLatestScreenCapture(): ScreenCapture | null {\n // Read current frame metadata\n const frameId = Atomics.load(this.screenAtomicState, this.FRAME_ID_INDEX);\n\n if (frameId <= this.lastProcessedFrameId) {\n return this.latestScreenCapture;\n }\n\n try {\n const width = Atomics.load(this.screenAtomicState, this.WIDTH_INDEX);\n const height = Atomics.load(this.screenAtomicState, this.HEIGHT_INDEX);\n const _displayIndex = Atomics.load(\n this.screenAtomicState,\n this.DISPLAY_INDEX,\n );\n const timestamp = Atomics.load(\n this.screenAtomicState,\n this.TIMESTAMP_INDEX,\n );\n\n // Create screen capture object\n this.latestScreenCapture = {\n timestamp,\n width,\n height,\n data: Buffer.alloc(0), // We don't copy the full data for performance\n tiles: this.generateTiles(width, height),\n };\n\n this.lastProcessedFrameId = frameId;\n } catch (error) {\n logger.error(\n \"[VisionWorkerManager] Failed to read screen capture:\",\n error,\n );\n }\n\n return this.latestScreenCapture;\n }\n\n getLatestEnhancedScene(): EnhancedSceneDescription {\n const screenCapture = this.getLatestScreenCapture();\n\n // Combine all Florence-2 results\n const florence2Captions: string[] = [];\n const allObjects: Array<{\n label: string;\n confidence: number;\n bbox: { x: number; y: number; width: number; height: number };\n }> = [];\n const allTags = new Set<string>();\n\n this.latestFlorence2Results.forEach((result) => {\n if (result.caption) {\n florence2Captions.push(result.caption);\n }\n if (result.objects) {\n allObjects.push(...result.objects);\n }\n if (result.tags) {\n for (const tag of result.tags) {\n allTags.add(tag);\n }\n }\n });\n\n const _tiles = this.generateTiles(\n screenCapture?.width || 0,\n screenCapture?.height || 0,\n );\n\n // Map allObjects to DetectedObject format\n const mappedObjects = allObjects.map((obj, index) => ({\n id: `obj-${index}`,\n type: obj.label,\n confidence: obj.confidence,\n boundingBox: obj.bbox,\n }));\n\n return {\n timestamp: Date.now(),\n description: florence2Captions.join(\". \"),\n objects: mappedObjects,\n people: [], // Could be populated by TensorFlow worker\n sceneChanged: true,\n changePercentage: 100,\n screenCapture: this.latestScreenCapture || undefined,\n screenAnalysis: {\n fullScreenOCR: this.latestOCRResult?.fullText,\n activeTile: {\n timestamp: Date.now(),\n florence2: this.latestFlorence2Results.values().next().value,\n ocr: this.latestOCRResult || undefined,\n },\n gridSummary: `${screenCapture?.tiles.length || 0} tiles analyzed`,\n uiElements: allObjects.map((obj) => ({\n type: obj.label,\n text: \"\",\n position: obj.bbox,\n })),\n },\n };\n }\n\n private generateTiles(\n width: number,\n height: number,\n ): Array<{\n id: string;\n row: number;\n col: number;\n x: number;\n y: number;\n width: number;\n height: number;\n }> {\n const tileSize = this.config.tileSize || 256;\n const tiles: Array<{\n id: string;\n row: number;\n col: number;\n x: number;\n y: number;\n width: number;\n height: number;\n }> = [];\n\n for (let row = 0; row < Math.ceil(height / tileSize); row++) {\n for (let col = 0; col < Math.ceil(width / tileSize); col++) {\n const x = col * tileSize;\n const y = row * tileSize;\n tiles.push({\n id: `tile-${row}-${col}`,\n row,\n col,\n x,\n y,\n width: Math.min(tileSize, width - x),\n height: Math.min(tileSize, height - y),\n });\n }\n }\n\n return tiles;\n }\n\n getWorkerStats(): Map<string, WorkerStats> {\n return new Map(this.workerStats);\n }\n\n async setDisplayIndex(index: number): Promise<void> {\n if (this.screenCaptureWorker) {\n this.screenCaptureWorker.postMessage({\n type: \"set_display\",\n displayIndex: index,\n });\n }\n }\n\n async setTextRegions(\n regions: Array<{ x: number; y: number; width: number; height: number }>,\n ): Promise<void> {\n if (this.ocrWorker) {\n this.ocrWorker.postMessage({\n type: \"update_regions\",\n regions,\n });\n }\n }\n\n async stop(): Promise<void> {\n logger.info(\"[VisionWorkerManager] Stopping all workers...\");\n\n const stopPromises: Promise<void>[] = [];\n\n if (this.screenCaptureWorker) {\n stopPromises.push(\n new Promise((resolve) => {\n this.screenCaptureWorker?.once(\"exit\", () => resolve());\n this.screenCaptureWorker?.postMessage({ type: \"stop\" });\n }),\n );\n }\n\n if (this.florence2Worker) {\n stopPromises.push(\n new Promise((resolve) => {\n this.florence2Worker?.once(\"exit\", () => resolve());\n this.florence2Worker?.postMessage({ type: \"stop\" });\n }),\n );\n }\n\n if (this.ocrWorker) {\n stopPromises.push(\n new Promise((resolve) => {\n this.ocrWorker?.once(\"exit\", () => resolve());\n this.ocrWorker?.postMessage({ type: \"stop\" });\n }),\n );\n }\n\n await Promise.all(stopPromises);\n logger.info(\"[VisionWorkerManager] All workers stopped\");\n }\n\n private handleWorkerLog(\n workerName: string,\n msg: { level: string; message: string; args: unknown[] },\n ): void {\n const { level, message, args } = msg;\n const formattedMessage = `[${workerName}] ${message}`;\n const stringArgs = args.map((arg) => String(arg));\n\n switch (level) {\n case \"info\":\n logger.info(formattedMessage, ...stringArgs);\n break;\n case \"warn\":\n logger.warn(formattedMessage, ...stringArgs);\n break;\n case \"error\":\n logger.error(formattedMessage, ...stringArgs);\n break;\n case \"debug\":\n logger.debug(formattedMessage, ...stringArgs);\n break;\n }\n }\n\n private async restartScreenCaptureWorker(): Promise<void> {\n const attempts = this.restartAttempts.get(\"screenCapture\") || 0;\n\n if (attempts >= this.MAX_RESTART_ATTEMPTS) {\n logger.error(\n \"[VisionWorkerManager] Max restart attempts reached for screen capture worker\",\n );\n return;\n }\n\n this.restartAttempts.set(\"screenCapture\", attempts + 1);\n logger.info(\n `[VisionWorkerManager] Restarting screen capture worker (attempt ${attempts + 1})`,\n );\n\n try {\n // Clean up existing worker\n if (this.screenCaptureWorker) {\n this.screenCaptureWorker.removeAllListeners();\n this.screenCaptureWorker = null;\n }\n\n // Start new worker\n await this.startScreenCaptureWorker();\n\n // Reset restart counter on successful start\n this.restartAttempts.set(\"screenCapture\", 0);\n } catch (error) {\n logger.error(\n \"[VisionWorkerManager] Failed to restart screen capture worker:\",\n error,\n );\n }\n }\n\n private async restartFlorence2Worker(): Promise<void> {\n const attempts = this.restartAttempts.get(\"florence2\") || 0;\n\n if (attempts >= this.MAX_RESTART_ATTEMPTS) {\n logger.error(\n \"[VisionWorkerManager] Max restart attempts reached for Florence2 worker\",\n );\n return;\n }\n\n this.restartAttempts.set(\"florence2\", attempts + 1);\n logger.info(\n `[VisionWorkerManager] Restarting Florence2 worker (attempt ${attempts + 1})`,\n );\n\n try {\n // Clean up existing worker\n if (this.florence2Worker) {\n this.florence2Worker.removeAllListeners();\n this.florence2Worker = null;\n }\n\n // Start new worker\n await this.startFlorence2Worker();\n\n // Reset restart counter on successful start\n this.restartAttempts.set(\"florence2\", 0);\n } catch (error) {\n logger.error(\n \"[VisionWorkerManager] Failed to restart Florence2 worker:\",\n error,\n );\n }\n }\n\n private async restartOCRWorker(): Promise<void> {\n const attempts = this.restartAttempts.get(\"ocr\") || 0;\n\n if (attempts >= this.MAX_RESTART_ATTEMPTS) {\n logger.error(\n \"[VisionWorkerManager] Max restart attempts reached for OCR worker\",\n );\n return;\n }\n\n this.restartAttempts.set(\"ocr\", attempts + 1);\n logger.info(\n `[VisionWorkerManager] Restarting OCR worker (attempt ${attempts + 1})`,\n );\n\n try {\n // Clean up existing worker\n if (this.ocrWorker) {\n this.ocrWorker.removeAllListeners();\n this.ocrWorker = null;\n }\n\n // Start new worker\n await this.startOCRWorker();\n\n // Reset restart counter on successful start\n this.restartAttempts.set(\"ocr\", 0);\n } catch (error) {\n logger.error(\n \"[VisionWorkerManager] Failed to restart OCR worker:\",\n error,\n );\n }\n }\n}\n",
22
+ "import type { IAgentRuntime, Memory } from \"@elizaos/core\";\nimport { createUniqueUuid } from \"@elizaos/core\";\nimport { visionAction } from \"../../action\";\nimport type { VisionService } from \"../../service\";\nimport { VisionMode } from \"../../types\";\n\nexport class ScreenVisionE2ETestSuite {\n name = \"plugin-vision-screen-e2e\";\n description =\n \"E2E tests for screen vision functionality including Florence-2 and OCR\";\n\n tests = [\n {\n name: \"Should initialize screen vision components\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing screen vision initialization...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n // Set vision mode to SCREEN\n await visionService.setVisionMode(VisionMode.SCREEN);\n\n // Wait for initialization\n await new Promise((resolve) => setTimeout(resolve, 2000));\n\n const mode = visionService.getVisionMode();\n if (mode !== VisionMode.SCREEN) {\n throw new Error(`Expected vision mode SCREEN but got ${mode}`);\n }\n\n console.log(\"✓ Screen vision mode activated\");\n\n // Check if screen capture is available\n const screenInfo = await visionService.getScreenCapture();\n if (screenInfo) {\n console.log(\n `✓ Screen capture available: ${screenInfo.width}x${screenInfo.height}`,\n );\n } else {\n console.log(\n \"⚠️ Screen capture not yet available (may still be initializing)\",\n );\n }\n },\n },\n\n {\n name: \"Should capture and tile screen\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing screen capture and tiling...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n // Ensure screen mode is active\n await visionService.setVisionMode(VisionMode.SCREEN);\n\n // Wait for capture\n await new Promise((resolve) => setTimeout(resolve, 3000));\n\n const screenCapture = await visionService.getScreenCapture();\n if (!screenCapture) {\n console.warn(\n \"⚠️ No screen capture available - screen capture may not be supported in this environment\",\n );\n return;\n }\n\n console.log(\n `✓ Screen captured: ${screenCapture.width}x${screenCapture.height}`,\n );\n console.log(`✓ Divided into ${screenCapture.tiles.length} tiles`);\n\n // Check tile structure\n const firstTile = screenCapture.tiles[0];\n if (!firstTile) {\n throw new Error(\"No tiles created from screen capture\");\n }\n\n console.log(\n ` First tile: ${firstTile.id} at (${firstTile.x}, ${firstTile.y})`,\n );\n console.log(` Tile size: ${firstTile.width}x${firstTile.height}`);\n\n // Check if priority tiles have data\n const tilesWithData = screenCapture.tiles.filter(\n (t) => t.data !== undefined,\n );\n console.log(` Tiles with data: ${tilesWithData.length}`);\n\n if (tilesWithData.length === 0) {\n console.warn(\"⚠️ No tiles have been processed yet\");\n }\n },\n },\n\n {\n name: \"Should analyze screen content with Florence-2 and OCR\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing screen content analysis...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n // Ensure screen mode is active\n await visionService.setVisionMode(VisionMode.SCREEN);\n\n // Wait for analysis\n await new Promise((resolve) => setTimeout(resolve, 5000));\n\n const enhancedScene = await visionService.getEnhancedSceneDescription();\n if (!enhancedScene || !enhancedScene.screenAnalysis) {\n console.warn(\"⚠️ No enhanced scene analysis available yet\");\n return;\n }\n\n console.log(\"✓ Enhanced scene analysis available\");\n\n const screenAnalysis = enhancedScene.screenAnalysis;\n\n // Check active tile analysis\n if (screenAnalysis.activeTile) {\n console.log(\"✓ Active tile analyzed\");\n\n if (screenAnalysis.activeTile.florence2) {\n console.log(\n ` Florence-2 caption: ${screenAnalysis.activeTile.florence2.caption}`,\n );\n console.log(\n ` Objects detected: ${screenAnalysis.activeTile.florence2.objects?.length || 0}`,\n );\n console.log(\n ` Tags: ${screenAnalysis.activeTile.florence2.tags?.join(\", \") || \"none\"}`,\n );\n }\n\n if (screenAnalysis.activeTile.ocr) {\n console.log(\n ` OCR text blocks: ${screenAnalysis.activeTile.ocr.blocks.length}`,\n );\n console.log(\n ` OCR preview: \"${screenAnalysis.activeTile.ocr.fullText.substring(0, 50)}...\"`,\n );\n }\n }\n\n // Check full screen OCR\n if (screenAnalysis.fullScreenOCR) {\n console.log(\n `✓ Full screen OCR: ${screenAnalysis.fullScreenOCR.length} characters`,\n );\n }\n\n // Check UI elements\n if (screenAnalysis.uiElements && screenAnalysis.uiElements.length > 0) {\n console.log(\n `✓ UI elements detected: ${screenAnalysis.uiElements.length}`,\n );\n const elementTypes = screenAnalysis.uiElements.map((e) => e.type);\n const uniqueTypes = [...new Set(elementTypes)];\n console.log(` Types: ${uniqueTypes.join(\", \")}`);\n }\n },\n },\n\n {\n name: \"Should switch between vision modes\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing vision mode switching...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n // Test all modes\n const modes = [\n VisionMode.CAMERA,\n VisionMode.SCREEN,\n VisionMode.BOTH,\n VisionMode.OFF,\n ];\n\n for (const mode of modes) {\n console.log(` Switching to ${mode} mode...`);\n await visionService.setVisionMode(mode);\n\n // Wait for mode switch\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n const currentMode = visionService.getVisionMode();\n if (currentMode !== mode) {\n throw new Error(\n `Failed to switch to ${mode} mode, current mode is ${currentMode}`,\n );\n }\n\n console.log(` ✓ Successfully switched to ${mode} mode`);\n }\n\n // Test with action\n console.log(\" Testing VISION action with op=set_mode...\");\n\n const message: Memory = {\n id: createUniqueUuid(runtime, \"test-msg\"),\n entityId: runtime.agentId,\n content: { text: \"set vision mode to both\" },\n agentId: runtime.agentId,\n roomId: createUniqueUuid(runtime, \"test-room\"),\n createdAt: Date.now(),\n };\n\n let callbackCalled = false;\n await visionAction.handler(\n runtime,\n message,\n { values: {}, data: {}, text: \"\" },\n { parameters: { op: \"set_mode\" } },\n async (response) => {\n callbackCalled = true;\n console.log(` Action response: ${response.text}`);\n return [];\n },\n );\n\n if (!callbackCalled) {\n throw new Error(\"VISION set_mode op did not call callback\");\n }\n\n const finalMode = visionService.getVisionMode();\n if (finalMode !== VisionMode.BOTH) {\n throw new Error(\n `SET_VISION_MODE action failed, mode is ${finalMode}`,\n );\n }\n\n console.log(\"✓ Vision mode switching works correctly\");\n },\n },\n\n {\n name: \"Should provide combined vision data in BOTH mode\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing combined camera and screen vision...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n // Set to BOTH mode\n await visionService.setVisionMode(VisionMode.BOTH);\n\n // Wait for both systems to initialize\n await new Promise((resolve) => setTimeout(resolve, 5000));\n\n const enhancedScene = await visionService.getEnhancedSceneDescription();\n const hasCamera = visionService.getCameraInfo() !== null;\n const hasScreen = (await visionService.getScreenCapture()) !== null;\n\n console.log(` Camera available: ${hasCamera}`);\n console.log(` Screen capture available: ${hasScreen}`);\n\n if (!hasCamera && !hasScreen) {\n console.warn(\n \"⚠️ Neither camera nor screen capture available in this environment\",\n );\n return;\n }\n\n if (enhancedScene) {\n // Check for camera data\n if (hasCamera && enhancedScene.description) {\n console.log(\"✓ Camera data present in combined mode\");\n console.log(\n ` Scene: ${enhancedScene.description.substring(0, 50)}...`,\n );\n }\n\n // Check for screen data\n if (hasScreen && enhancedScene.screenAnalysis) {\n console.log(\"✓ Screen data present in combined mode\");\n console.log(` Grid: ${enhancedScene.screenAnalysis.gridSummary}`);\n }\n }\n\n // Check provider output\n const state = await runtime.composeState({\n id: createUniqueUuid(runtime, \"test-msg\"),\n entityId: runtime.agentId,\n content: { text: \"test\" },\n agentId: runtime.agentId,\n roomId: createUniqueUuid(runtime, \"test-room\"),\n createdAt: Date.now(),\n });\n\n if (state.text.includes(\"Vision mode: BOTH\")) {\n console.log(\"✓ Provider correctly reports BOTH mode\");\n }\n },\n },\n\n {\n name: \"Should handle screen capture errors gracefully\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing error handling...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n // Try to set invalid region (should handle gracefully)\n // Access private property for testing purposes\n type TestVisionConfig = {\n screenRegion?: {\n x: number;\n y: number;\n width: number;\n height: number;\n };\n };\n const originalConfig = Reflect.get(\n visionService,\n \"visionConfig\",\n ) as TestVisionConfig;\n const invalidConfig: TestVisionConfig = {\n ...originalConfig,\n screenRegion: {\n x: -100,\n y: -100,\n width: 50000,\n height: 50000,\n },\n };\n Reflect.set(visionService, \"visionConfig\", invalidConfig);\n\n await visionService.setVisionMode(VisionMode.SCREEN);\n await new Promise((resolve) => setTimeout(resolve, 2000));\n\n // Service should still be active despite invalid region\n const isActive = visionService.isActive();\n console.log(` Service active after invalid config: ${isActive}`);\n\n // Restore config\n Reflect.set(visionService, \"visionConfig\", originalConfig);\n\n console.log(\"✓ Error handling works correctly\");\n },\n },\n ];\n}\n\nexport default new ScreenVisionE2ETestSuite();\n",
23
+ "import type {\n Content,\n IAgentRuntime,\n Memory,\n ServiceTypeName,\n State,\n} from \"@elizaos/core\";\nimport { createUniqueUuid } from \"@elizaos/core\";\nimport { visionAction } from \"../../action\";\nimport type { VisionService } from \"../../service\";\n\nexport class VisionBasicE2ETestSuite {\n name = \"plugin-vision-basic-e2e\";\n description = \"Basic end-to-end tests for vision plugin functionality\";\n\n tests = [\n {\n name: \"Should initialize vision service\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing vision service initialization...\");\n\n const visionService = runtime.getService<VisionService>(\n \"VISION\" as ServiceTypeName,\n );\n if (!visionService) {\n throw new Error(\n \"Vision service not available - service must be registered\",\n );\n }\n\n // Check if service is active\n const isActive = visionService.isActive();\n\n // Get camera info\n const cameraInfo = visionService.getCameraInfo();\n\n if (!isActive || !cameraInfo) {\n // For CI/CD environments without cameras, check that service at least initializes\n console.warn(\n \"⚠️ No camera detected. Service initialized but not active.\",\n );\n console.log(\n \" This is acceptable in CI/CD environments without cameras.\",\n );\n } else {\n console.log(\"✓ Vision service initialized and active\");\n console.log(\n `✓ Connected to camera: ${cameraInfo.name} (ID: ${cameraInfo.id})`,\n );\n }\n },\n },\n\n {\n name: \"Should describe scene when requested\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing scene description action...\");\n\n const roomId = createUniqueUuid(runtime, \"test-room\");\n const message: Memory = {\n id: createUniqueUuid(runtime, \"test-msg-describe\"),\n entityId: runtime.agentId,\n content: { text: \"what do you see?\" },\n agentId: runtime.agentId,\n roomId,\n createdAt: Date.now(),\n };\n\n let callbackCalled = false;\n let callbackResponse: Content | null = null;\n\n const state: State = { values: {}, data: {}, text: \"\" };\n\n // Get vision service to check if active\n const visionService = runtime.getService<VisionService>(\n \"VISION\" as ServiceTypeName,\n );\n\n // Validate the action\n const isValid = await visionAction.validate(runtime, message, state);\n\n if (!visionService || !visionService.isActive()) {\n // If vision service is not active, validation should return false\n if (isValid) {\n throw new Error(\n \"Action validation should return false when vision service is not active\",\n );\n }\n console.log(\n \" Action validation correctly returned false (vision not active)\",\n );\n\n // But handler should still work and provide appropriate message\n await visionAction.handler(\n runtime,\n message,\n state,\n { parameters: { op: \"describe\" } },\n async (response) => {\n callbackCalled = true;\n callbackResponse = response;\n return [];\n },\n );\n\n if (!callbackCalled) {\n throw new Error(\"Callback was not called - action handler failed\");\n }\n\n if (!callbackResponse || !callbackResponse.text) {\n throw new Error(\"No response text returned from action\");\n }\n\n console.log(\n \"✓ Scene description action handled unavailability correctly\",\n );\n console.log(` Response: ${callbackResponse.text}`);\n\n // Verify it indicates camera not available\n if (\n !callbackResponse.text.includes(\"cannot see\") &&\n !callbackResponse.text.includes(\"no camera\")\n ) {\n throw new Error(\"Response does not indicate camera unavailability\");\n }\n } else {\n // Vision is active, normal test flow\n if (!isValid) {\n throw new Error(\n \"visionAction validation failed despite active vision\",\n );\n }\n console.log(\" Action validation: passed\");\n\n await visionAction.handler(\n runtime,\n message,\n state,\n { parameters: { op: \"describe\" } },\n async (response) => {\n callbackCalled = true;\n callbackResponse = response;\n return [];\n },\n );\n\n if (!callbackCalled) {\n throw new Error(\"Callback was not called - action handler failed\");\n }\n\n if (!callbackResponse || !callbackResponse.text) {\n throw new Error(\"No response text returned from action\");\n }\n\n console.log(\"✓ Scene description action executed\");\n console.log(` Response: ${callbackResponse.text}`);\n if (callbackResponse.thought) {\n console.log(` Thought: ${callbackResponse.thought}`);\n }\n }\n\n // Verify response contains expected action\n if (\n !callbackResponse.actions ||\n !callbackResponse.actions.includes(\"VISION\")\n ) {\n throw new Error(\"Response does not include VISION action\");\n }\n },\n },\n\n {\n name: \"Should capture image when requested\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing image capture action...\");\n\n const roomId = createUniqueUuid(runtime, \"test-room\");\n const message: Memory = {\n id: createUniqueUuid(runtime, \"test-msg-capture\"),\n entityId: runtime.agentId,\n content: { text: \"take a photo\" },\n agentId: runtime.agentId,\n roomId,\n createdAt: Date.now(),\n };\n\n let callbackCalled = false;\n let callbackResponse: Content | null = null;\n\n const state: State = { values: {}, data: {}, text: \"\" };\n\n // Get vision service to check if active\n const visionService = runtime.getService<VisionService>(\n \"VISION\" as ServiceTypeName,\n );\n\n // Validate the action\n const isValid = await visionAction.validate(runtime, message, state);\n\n if (!visionService || !visionService.isActive()) {\n // If vision service is not active, validation should return false\n if (isValid) {\n throw new Error(\n \"Action validation should return false when vision service is not active\",\n );\n }\n console.log(\n \" Action validation correctly returned false (vision not active)\",\n );\n\n // But handler should still work and provide appropriate message\n await visionAction.handler(\n runtime,\n message,\n state,\n { parameters: { op: \"capture\" } },\n async (response) => {\n callbackCalled = true;\n callbackResponse = response;\n return [];\n },\n );\n\n if (!callbackCalled) {\n throw new Error(\"Callback was not called - action handler failed\");\n }\n\n if (!callbackResponse || !callbackResponse.text) {\n throw new Error(\"No response text returned from action\");\n }\n\n console.log(\n \"✓ Image capture action handled unavailability correctly\",\n );\n console.log(` Response: ${callbackResponse.text}`);\n\n // Verify it indicates camera not available\n if (\n !callbackResponse.text.includes(\"cannot capture\") &&\n !callbackResponse.text.includes(\"no camera\")\n ) {\n throw new Error(\"Response does not indicate camera unavailability\");\n }\n } else {\n // Vision is active, normal test flow\n if (!isValid) {\n throw new Error(\n \"visionAction validation failed despite active vision\",\n );\n }\n console.log(\" Action validation: passed\");\n\n await visionAction.handler(\n runtime,\n message,\n state,\n { parameters: { op: \"capture\" } },\n async (response) => {\n callbackCalled = true;\n callbackResponse = response;\n return [];\n },\n );\n\n if (!callbackCalled) {\n throw new Error(\"Callback was not called - action handler failed\");\n }\n\n if (!callbackResponse || !callbackResponse.text) {\n throw new Error(\"No response text returned from action\");\n }\n\n console.log(\"✓ Image capture action executed\");\n console.log(` Response: ${callbackResponse.text}`);\n\n // If camera is active, we should have an attachment\n if (\n !callbackResponse.attachments ||\n callbackResponse.attachments.length === 0\n ) {\n throw new Error(\n \"No image attachment returned despite active camera\",\n );\n }\n\n const attachment = callbackResponse.attachments[0];\n if (!attachment.url || !attachment.url.startsWith(\"data:image/\")) {\n throw new Error(\"Invalid image attachment format\");\n }\n\n console.log(` ✓ Image attachment valid: ${attachment.title}`);\n }\n\n // Verify response contains expected action\n if (\n !callbackResponse.actions ||\n !callbackResponse.actions.includes(\"VISION\")\n ) {\n throw new Error(\"Response does not include VISION action\");\n }\n },\n },\n\n {\n name: \"Should provide vision context through provider\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing vision provider...\");\n\n // Compose state to trigger providers\n const message: Memory = {\n id: createUniqueUuid(runtime, \"test-msg-provider\"),\n entityId: runtime.agentId,\n content: { text: \"test provider\" },\n agentId: runtime.agentId,\n roomId: createUniqueUuid(runtime, \"test-room\"),\n createdAt: Date.now(),\n };\n\n const state = await runtime.composeState(message);\n\n // Vision provider should always add data\n if (state.values.visionAvailable === undefined) {\n throw new Error(\n \"Vision provider data missing - provider not registered or failed\",\n );\n }\n\n console.log(\"✓ Vision provider data found in state\");\n console.log(` Vision available: ${state.values.visionAvailable}`);\n console.log(` Camera status: ${state.values.cameraStatus}`);\n\n // Verify vision context in formatted text\n if (!state.text.includes(\"Visual Perception\")) {\n throw new Error(\"Vision context not included in state text\");\n }\n console.log(\"✓ Vision context included in state text\");\n\n // If vision is available, verify scene data\n if (state.values.visionAvailable && state.values.sceneDescription) {\n console.log(` Scene description: ${state.values.sceneDescription}`);\n }\n },\n },\n\n {\n name: \"Should handle scene changes efficiently\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing scene change detection...\");\n\n const visionService = runtime.getService<VisionService>(\n \"VISION\" as ServiceTypeName,\n );\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n if (!visionService.isActive()) {\n console.warn(\n \"⚠️ Vision service not active - skipping scene change test\",\n );\n console.log(\" This is acceptable in environments without cameras\");\n return;\n }\n\n // Get initial scene description\n const initialScene = await visionService.getSceneDescription();\n console.log(\n ` Initial scene: ${initialScene ? \"Available\" : \"Pending...\"}`,\n );\n\n // Wait for scene processing\n await new Promise((resolve) => setTimeout(resolve, 2000));\n\n // Get updated scene description\n const updatedScene = await visionService.getSceneDescription();\n\n if (!updatedScene) {\n throw new Error(\"No scene description available after 2 seconds\");\n }\n\n console.log(\"✓ Scene monitoring active\");\n console.log(\n ` Scene timestamp: ${new Date(updatedScene.timestamp).toISOString()}`,\n );\n console.log(\n ` Description: ${updatedScene.description.substring(0, 100)}...`,\n );\n\n if (updatedScene.changePercentage !== undefined) {\n console.log(\n ` Last change: ${updatedScene.changePercentage.toFixed(1)}%`,\n );\n }\n },\n },\n\n {\n name: \"Should detect objects and people in scene\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing object and person detection...\");\n\n const visionService = runtime.getService<VisionService>(\n \"VISION\" as ServiceTypeName,\n );\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n if (!visionService.isActive()) {\n console.warn(\n \"⚠️ Vision service not active - skipping detection test\",\n );\n console.log(\" This is acceptable in environments without cameras\");\n return;\n }\n\n // Wait for scene processing to accumulate frames\n console.log(\" Waiting for scene analysis...\");\n await new Promise((resolve) => setTimeout(resolve, 3000));\n\n // Get scene description\n const scene = await visionService.getSceneDescription();\n\n if (!scene) {\n throw new Error(\"No scene description available after 3 seconds\");\n }\n\n console.log(\"✓ Scene analysis complete\");\n console.log(` Description: ${scene.description.substring(0, 100)}...`);\n console.log(` Objects detected: ${scene.objects.length}`);\n console.log(` People detected: ${scene.people.length}`);\n\n // Verify object detection\n if (scene.objects.length > 0) {\n console.log(\" Detected objects:\");\n const objectTypes = scene.objects.reduce(\n (acc, obj) => {\n acc[obj.type] = (acc[obj.type] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>,\n );\n\n for (const [type, count] of Object.entries(objectTypes)) {\n console.log(` - ${count} ${type}(s)`);\n }\n\n // Verify objects have required fields\n for (const obj of scene.objects) {\n if (\n !obj.id ||\n !obj.type ||\n obj.confidence === undefined ||\n !obj.boundingBox\n ) {\n throw new Error(\"Detected object missing required fields\");\n }\n }\n }\n\n // Verify person detection\n if (scene.people.length > 0) {\n console.log(\" Detected people:\");\n for (const person of scene.people) {\n console.log(\n ` - Person ${person.id}: ${person.pose} pose, facing ${person.facing}, confidence ${person.confidence.toFixed(2)}`,\n );\n\n // Verify person has required fields\n if (\n !person.id ||\n !person.pose ||\n !person.facing ||\n person.confidence === undefined ||\n !person.boundingBox\n ) {\n throw new Error(\"Detected person missing required fields\");\n }\n }\n }\n\n // If there's motion, we should detect something\n if (scene.changePercentage > 10) {\n console.log(` Scene change: ${scene.changePercentage.toFixed(1)}%`);\n if (scene.objects.length === 0 && scene.people.length === 0) {\n console.warn(\n \" ⚠️ Significant scene change but no objects/people detected\",\n );\n console.log(\n \" This might indicate the motion detection threshold needs adjustment\",\n );\n }\n }\n },\n },\n ];\n}\n\nexport default new VisionBasicE2ETestSuite();\n",
24
+ "import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport type { IAgentRuntime } from \"@elizaos/core\";\nimport type { VisionService } from \"../../service\";\n\n/** A single vision capture entry (success or error) */\ninterface VisionCaptureEntry {\n index: number;\n timestamp: string;\n timestampMs?: number;\n elapsedMs?: number;\n scene?: {\n description: string;\n changePercentage: number;\n sceneChanged: boolean;\n objectCount: number;\n peopleCount: number;\n objects: { type: string }[];\n people: { pose: string }[];\n } | null;\n frame?: {\n width: number;\n height: number;\n format: string;\n timestamp: number;\n } | null;\n imageBase64?: string | null;\n error?: string;\n}\n\nexport class VisionCaptureLogTestSuite {\n name = \"plugin-vision-capture-log\";\n description =\n \"Captures 30 seconds of vision data and saves to logs for analysis\";\n\n tests = [\n {\n name: \"Should capture and log 30 seconds of vision data\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Starting 30-second vision capture test...\");\n\n const visionService = runtime.getService<VisionService>(\"VISION\");\n if (!visionService) {\n throw new Error(\"Vision service not available\");\n }\n\n if (!visionService.isActive()) {\n console.warn(\"⚠️ Vision service not active - no camera available\");\n console.log(\" Cannot capture vision data without a camera\");\n return;\n }\n\n // Create logs directory if it doesn't exist\n const logsDir = path.join(process.cwd(), \"logs\");\n const sessionDir = path.join(\n logsDir,\n `vision-capture-${new Date().toISOString().replace(/[:.]/g, \"-\")}`,\n );\n await fs.mkdir(sessionDir, { recursive: true });\n\n console.log(`✓ Created log directory: ${sessionDir}`);\n\n // Initialize capture data\n const captureData = {\n sessionId: `vision-capture-${Date.now()}`,\n startTime: new Date().toISOString(),\n endTime: \"\",\n runtime: {\n agentId: runtime.agentId,\n characterName: runtime.character.name,\n },\n camera: visionService.getCameraInfo(),\n captures: [] as VisionCaptureEntry[],\n statistics: {\n totalFrames: 0,\n totalSceneChanges: 0,\n totalObjectsDetected: 0,\n totalPeopleDetected: 0,\n averageChangePercentage: 0,\n objectTypeCounts: {} as Record<string, number>,\n poseCounts: {} as Record<string, number>,\n },\n };\n\n // Capture interval - every 500ms for 30 seconds = 60 captures\n const captureInterval = 500;\n const totalDuration = 30000;\n const expectedCaptures = totalDuration / captureInterval;\n\n console.log(\n `📸 Capturing vision data every ${captureInterval}ms for ${totalDuration / 1000} seconds...`,\n );\n console.log(` Expected captures: ${expectedCaptures}`);\n\n let captureCount = 0;\n let totalChangePercentage = 0;\n let lastLoggedProgress = 0;\n\n const startTime = Date.now();\n\n while (Date.now() - startTime < totalDuration) {\n const captureStartTime = Date.now();\n\n try {\n // Get current scene description\n const scene = await visionService.getSceneDescription();\n const frame = await visionService.getCurrentFrame();\n\n // Capture image as base64\n const imageBuffer = await visionService.captureImage();\n let imageBase64: string | null = null;\n if (imageBuffer) {\n imageBase64 = imageBuffer.toString(\"base64\");\n }\n\n const capture = {\n index: captureCount,\n timestamp: new Date().toISOString(),\n timestampMs: Date.now(),\n elapsedMs: Date.now() - startTime,\n scene: scene\n ? {\n description: scene.description,\n changePercentage: scene.changePercentage,\n sceneChanged: scene.sceneChanged,\n objectCount: scene.objects.length,\n peopleCount: scene.people.length,\n objects: scene.objects,\n people: scene.people,\n }\n : null,\n frame: frame\n ? {\n width: frame.width,\n height: frame.height,\n format: frame.format,\n timestamp: frame.timestamp,\n }\n : null,\n imageBase64: imageBase64 ?? null,\n };\n\n captureData.captures.push(capture);\n\n // Save full image separately\n if (imageBase64) {\n const imagePath = path.join(\n sessionDir,\n `capture-${String(captureCount).padStart(3, \"0\")}.jpg`,\n );\n await fs.writeFile(imagePath, Buffer.from(imageBase64, \"base64\"));\n }\n\n // Update statistics\n if (scene) {\n captureData.statistics.totalFrames++;\n if (scene.sceneChanged) {\n captureData.statistics.totalSceneChanges++;\n }\n if (scene.changePercentage) {\n totalChangePercentage += scene.changePercentage;\n }\n captureData.statistics.totalObjectsDetected +=\n scene.objects.length;\n captureData.statistics.totalPeopleDetected += scene.people.length;\n\n // Count object types\n for (const obj of scene.objects) {\n captureData.statistics.objectTypeCounts[obj.type] =\n (captureData.statistics.objectTypeCounts[obj.type] || 0) + 1;\n }\n\n // Count poses\n for (const person of scene.people) {\n captureData.statistics.poseCounts[person.pose] =\n (captureData.statistics.poseCounts[person.pose] || 0) + 1;\n }\n\n // Save detailed scene log\n const sceneLogPath = path.join(\n sessionDir,\n `scene-${String(captureCount).padStart(3, \"0\")}.json`,\n );\n await fs.writeFile(\n sceneLogPath,\n JSON.stringify(\n {\n capture: captureCount,\n timestamp: capture.timestamp,\n scene,\n frame: frame\n ? {\n width: frame.width,\n height: frame.height,\n format: frame.format,\n }\n : null,\n },\n null,\n 2,\n ),\n );\n }\n\n captureCount++;\n\n // Progress logging every 5 seconds\n const elapsedSeconds = Math.floor((Date.now() - startTime) / 1000);\n if (\n elapsedSeconds > lastLoggedProgress &&\n elapsedSeconds % 5 === 0\n ) {\n lastLoggedProgress = elapsedSeconds;\n const progress = (elapsedSeconds / 30) * 100;\n console.log(\n ` Progress: ${progress.toFixed(0)}% (${elapsedSeconds}/30s) - Captured ${captureCount} frames`,\n );\n\n if (scene) {\n console.log(\n ` Last scene: \"${scene.description.substring(0, 60)}...\"`,\n );\n if (scene.objects.length > 0 || scene.people.length > 0) {\n console.log(\n ` Detected: ${scene.objects.length} objects, ${scene.people.length} people`,\n );\n }\n }\n }\n } catch (error) {\n console.error(` Error in capture ${captureCount}:`, error);\n captureData.captures.push({\n index: captureCount,\n timestamp: new Date().toISOString(),\n error: error instanceof Error ? error.message : String(error),\n });\n captureCount++;\n }\n\n // Wait for next capture interval\n const captureEndTime = Date.now();\n const captureDuration = captureEndTime - captureStartTime;\n const waitTime = Math.max(0, captureInterval - captureDuration);\n\n if (waitTime > 0) {\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n }\n }\n\n // Finalize statistics\n captureData.endTime = new Date().toISOString();\n captureData.statistics.averageChangePercentage =\n captureData.statistics.totalFrames > 0\n ? totalChangePercentage / captureData.statistics.totalFrames\n : 0;\n\n // Save main capture log\n const mainLogPath = path.join(\n sessionDir,\n \"vision-capture-summary.json\",\n );\n await fs.writeFile(mainLogPath, JSON.stringify(captureData, null, 2));\n\n // Generate markdown report\n const reportPath = path.join(sessionDir, \"vision-capture-report.md\");\n const report = `# Vision Capture Report\n\n## Session Information\n- **Session ID**: ${captureData.sessionId}\n- **Start Time**: ${captureData.startTime}\n- **End Time**: ${captureData.endTime}\n- **Duration**: 30 seconds\n- **Agent**: ${captureData.runtime.characterName} (${captureData.runtime.agentId})\n\n## Camera Information\n- **Name**: ${captureData.camera?.name || \"Unknown\"}\n- **ID**: ${captureData.camera?.id || \"Unknown\"}\n\n## Capture Statistics\n- **Total Frames Captured**: ${captureCount}\n- **Total Scene Changes**: ${captureData.statistics.totalSceneChanges}\n- **Average Change Percentage**: ${captureData.statistics.averageChangePercentage.toFixed(2)}%\n- **Total Objects Detected**: ${captureData.statistics.totalObjectsDetected}\n- **Total People Detected**: ${captureData.statistics.totalPeopleDetected}\n\n## Object Type Distribution\n${\n Object.entries(captureData.statistics.objectTypeCounts)\n .sort(([, a], [, b]) => b - a)\n .map(([type, count]) => `- **${type}**: ${count} detections`)\n .join(\"\\n\") || \"- No objects detected\"\n}\n\n## Pose Distribution\n${\n Object.entries(captureData.statistics.poseCounts)\n .map(([pose, count]) => `- **${pose}**: ${count} detections`)\n .join(\"\\n\") || \"- No people detected\"\n}\n\n## Sample Scene Descriptions\n${captureData.captures\n .filter((c) => c.scene?.description)\n .slice(0, 5)\n .map(\n (c, _i) => `### Capture ${c.index} (${c.elapsedMs ?? 0}ms)\n\"${c.scene?.description ?? \"\"}\"\n- Change: ${c.scene?.changePercentage?.toFixed(1) ?? \"0\"}%\n- Objects: ${c.scene?.objectCount ?? 0}\n- People: ${c.scene?.peopleCount ?? 0}`,\n )\n .join(\"\\n\\n\")}\n\n## Files Generated\n- \\`vision-capture-summary.json\\` - Complete capture data\n- \\`vision-capture-report.md\\` - This report\n- \\`capture-XXX.jpg\\` - Individual captured images\n- \\`scene-XXX.json\\` - Detailed scene data for each capture\n`;\n\n await fs.writeFile(reportPath, report);\n\n console.log(\"\\n✅ Vision capture test completed!\");\n console.log(\"📊 Capture Summary:\");\n console.log(` - Total frames: ${captureCount}`);\n console.log(\n ` - Scene changes: ${captureData.statistics.totalSceneChanges}`,\n );\n console.log(\n ` - Average change: ${captureData.statistics.averageChangePercentage.toFixed(2)}%`,\n );\n console.log(\n ` - Objects detected: ${captureData.statistics.totalObjectsDetected}`,\n );\n console.log(\n ` - People detected: ${captureData.statistics.totalPeopleDetected}`,\n );\n console.log(`\\n📁 Results saved to: ${sessionDir}`);\n console.log(\" - Summary: vision-capture-summary.json\");\n console.log(\" - Report: vision-capture-report.md\");\n console.log(\" - Images: capture-XXX.jpg\");\n console.log(\" - Scene data: scene-XXX.json\");\n\n console.log(\"✅ Vision capture log test PASSED\");\n },\n },\n ];\n}\n\nexport default new VisionCaptureLogTestSuite();\n",
25
+ "import type { Action, Content, IAgentRuntime, Provider } from \"@elizaos/core\";\nimport { logger } from \"@elizaos/core\";\nimport type { VisionService } from \"../../service\";\nimport { VisionMode, VisionServiceType } from \"../../types\";\n\nexport class VisionRuntimeTestSuite {\n name = \"vision-runtime-tests\";\n description = \"Real runtime tests for vision plugin functionality\";\n\n tests = [\n {\n name: \"Vision service initialization\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing vision service initialization...\");\n\n const visionService = runtime.getService<VisionService>(\n VisionServiceType.VISION,\n );\n if (!visionService) {\n throw new Error(\"Vision service not found in runtime\");\n }\n\n // Check if service is properly initialized\n if (typeof visionService.isActive !== \"function\") {\n throw new Error(\"Vision service missing isActive method\");\n }\n\n const isActive = visionService.isActive();\n logger.info(`[Test] Vision service active: ${isActive}`);\n\n // Service should be active after initialization\n if (!isActive && runtime.getSetting(\"VISION_MODE\") !== VisionMode.OFF) {\n throw new Error(\"Vision service should be active but is not\");\n }\n\n logger.info(\"[Test] ✅ Vision service initialization test passed\");\n },\n },\n\n {\n name: \"Scene description functionality\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing scene description...\");\n\n const visionService = runtime.getService<VisionService>(\n VisionServiceType.VISION,\n );\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Get current scene description\n const scene = await visionService.getSceneDescription();\n\n if (!scene) {\n logger.warn(\n \"[Test] No scene description available (camera might not be connected)\",\n );\n return; // Don't fail if no camera\n }\n\n // Validate scene structure\n if (typeof scene.timestamp !== \"number\") {\n throw new Error(\"Scene description missing timestamp\");\n }\n\n if (typeof scene.description !== \"string\") {\n throw new Error(\"Scene description missing description text\");\n }\n\n if (!Array.isArray(scene.objects)) {\n throw new Error(\"Scene description missing objects array\");\n }\n\n if (!Array.isArray(scene.people)) {\n throw new Error(\"Scene description missing people array\");\n }\n\n logger.info(`[Test] Scene: ${scene.description.substring(0, 100)}...`);\n logger.info(\n `[Test] Objects: ${scene.objects.length}, People: ${scene.people.length}`,\n );\n logger.info(\"[Test] ✅ Scene description test passed\");\n },\n },\n\n {\n name: \"Vision mode switching\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing vision mode switching...\");\n\n const visionService = runtime.getService<VisionService>(\n VisionServiceType.VISION,\n );\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Get current mode\n const originalMode = visionService.getVisionMode();\n logger.info(`[Test] Original mode: ${originalMode}`);\n\n // Test switching modes\n const testModes: VisionMode[] = [\n VisionMode.CAMERA,\n VisionMode.SCREEN,\n VisionMode.BOTH,\n VisionMode.OFF,\n ];\n\n for (const mode of testModes) {\n logger.info(`[Test] Switching to mode: ${mode}`);\n await visionService.setVisionMode(mode);\n\n const currentMode = visionService.getVisionMode();\n if (currentMode !== mode) {\n throw new Error(\n `Failed to switch to mode ${mode}, current mode is ${currentMode}`,\n );\n }\n }\n\n // Restore original mode\n await visionService.setVisionMode(originalMode);\n logger.info(\"[Test] ✅ Vision mode switching test passed\");\n },\n },\n\n {\n name: \"VISION action describe op execution\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing VISION action with op=describe...\");\n\n // Find the action\n const action = (runtime.actions as Action[]).find(\n (a) => a.name === \"VISION\",\n );\n if (!action) {\n throw new Error(\"VISION action not found\");\n }\n\n // Create test message\n const message = {\n id: `test-msg-${Date.now()}`,\n entityId: \"test-entity\",\n roomId: \"test-room\",\n content: {\n text: \"Describe what you see\",\n source: \"test\",\n },\n createdAt: Date.now(),\n };\n\n // Validate action\n const isValid = await action.validate(runtime, message);\n if (!isValid) {\n throw new Error(\"VISION action validation failed\");\n }\n\n // Execute action\n let responseReceived = false;\n const callback = async (response: Content) => {\n if (response.text && response.text.length > 0) {\n responseReceived = true;\n logger.info(\n `[Test] Action response: ${response.text.substring(0, 100)}...`,\n );\n }\n return [];\n };\n\n await action.handler(\n runtime,\n message,\n { values: {}, data: {}, text: \"\" },\n { parameters: { op: \"describe\" } },\n callback,\n );\n\n if (!responseReceived) {\n throw new Error(\n \"VISION action with op=describe did not produce a response\",\n );\n }\n\n logger.info(\"[Test] ✅ VISION action describe op test passed\");\n },\n },\n\n {\n name: \"Vision provider integration\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing vision provider...\");\n\n // Find the vision provider\n const provider = (runtime.providers as Provider[]).find(\n (p) => p.name === \"visionProvider\",\n );\n if (!provider) {\n throw new Error(\"Vision provider not found\");\n }\n\n // Create test message and state\n const message = {\n id: `test-msg-${Date.now()}`,\n entityId: \"test-entity\",\n roomId: \"test-room\",\n content: { text: \"test\", source: \"test\" },\n createdAt: Date.now(),\n };\n\n const state = {\n values: {},\n data: {},\n text: \"\",\n };\n\n // Get provider data\n const result = await provider.get(runtime, message, state);\n\n if (!result || typeof result !== \"object\") {\n throw new Error(\"Vision provider returned invalid result\");\n }\n\n // Check if provider returns vision data when available\n if (result.text?.includes(\"I can see\")) {\n logger.info(\n `[Test] Provider text: ${result.text.substring(0, 100)}...`,\n );\n }\n\n logger.info(\"[Test] ✅ Vision provider test passed\");\n },\n },\n\n {\n name: \"Florence-2 model initialization\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing Florence-2 model...\");\n\n const visionService = runtime.getService<VisionService>(\n VisionServiceType.VISION,\n );\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Check if Florence-2 is enabled\n const florence2Enabled =\n runtime.getSetting(\"FLORENCE2_ENABLED\") === \"true\" ||\n runtime.getSetting(\"VISION_FLORENCE2_ENABLED\") === \"true\";\n\n if (!florence2Enabled) {\n logger.info(\"[Test] Florence-2 is disabled, skipping test\");\n return;\n }\n\n // If screen mode is enabled, Florence-2 should be initialized\n const mode = visionService.getVisionMode();\n if (mode === VisionMode.SCREEN || mode === VisionMode.BOTH) {\n // Try to get screen capture\n const screenCapture = await visionService.getScreenCapture();\n if (screenCapture) {\n logger.info(\"[Test] Screen capture available\");\n logger.info(\n `[Test] Screen size: ${screenCapture.width}x${screenCapture.height}`,\n );\n logger.info(`[Test] Tiles: ${screenCapture.tiles.length}`);\n }\n }\n\n logger.info(\"[Test] ✅ Florence-2 model test passed\");\n },\n },\n\n {\n name: \"OCR service functionality\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing OCR service...\");\n\n const visionService = runtime.getService<VisionService>(\n VisionServiceType.VISION,\n );\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Check if OCR is enabled\n const ocrEnabled =\n runtime.getSetting(\"OCR_ENABLED\") === \"true\" ||\n runtime.getSetting(\"VISION_OCR_ENABLED\") === \"true\";\n\n if (!ocrEnabled) {\n logger.info(\"[Test] OCR is disabled, skipping test\");\n return;\n }\n\n // If screen mode is enabled, OCR should work\n const mode = visionService.getVisionMode();\n if (mode === VisionMode.SCREEN || mode === VisionMode.BOTH) {\n const enhancedScene =\n await visionService.getEnhancedSceneDescription();\n if (enhancedScene?.screenAnalysis) {\n const ocrText = enhancedScene.screenAnalysis.fullScreenOCR;\n if (ocrText) {\n logger.info(`[Test] OCR extracted ${ocrText.length} characters`);\n logger.info(`[Test] OCR sample: ${ocrText.substring(0, 100)}...`);\n }\n }\n }\n\n logger.info(\"[Test] ✅ OCR service test passed\");\n },\n },\n\n {\n name: \"Entity tracking system\",\n fn: async (runtime: IAgentRuntime) => {\n logger.info(\"[Test] Testing entity tracking...\");\n\n const visionService = runtime.getService<VisionService>(\n VisionServiceType.VISION,\n );\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Get entity tracker\n const entityTracker = visionService.getEntityTracker();\n if (!entityTracker) {\n throw new Error(\"Entity tracker not found\");\n }\n\n // Get current entities\n const entities = entityTracker.getActiveEntities();\n logger.info(`[Test] Active entities: ${entities.length}`);\n\n // Check entity structure if any exist\n for (const entity of entities) {\n if (!entity.id || !entity.entityType || !entity.lastSeen) {\n throw new Error(\"Entity missing required fields\");\n }\n\n logger.info(\n `[Test] Entity ${entity.id}: type=${entity.entityType}, tracked=${entity.lastSeen - entity.firstSeen}ms`,\n );\n }\n\n logger.info(\"[Test] ✅ Entity tracking test passed\");\n },\n },\n ];\n}\n\n// Export default instance for test runner\nexport default new VisionRuntimeTestSuite();\n",
26
+ "import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { IAgentRuntime } from \"@elizaos/core\";\nimport type { VisionService } from \"../../service\";\nimport { VisionServiceType } from \"../../types\";\nimport {\n generateComplexPattern,\n generateQuadrantPattern,\n savePattern,\n verifyQuadrantNumbers,\n} from \"../test-pattern-generator\";\n\nconst execAsync = promisify(exec);\n\nexport class VisionWorkerE2ETestSuite {\n name = \"plugin-vision-workers-e2e\";\n description =\n \"E2E tests for multi-threaded vision system with worker threads\";\n\n tests = [\n {\n name: \"Should access vision service through runtime\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing vision service access through runtime...\");\n\n // Get vision service from runtime\n const visionService = runtime.getService<VisionService>(\n VisionServiceType.VISION,\n );\n\n if (!visionService) {\n throw new Error(\"Vision service not found in runtime\");\n }\n\n console.log(\"✓ Vision service found in runtime\");\n\n // Check if service is active\n const isActive = visionService.isActive();\n console.log(`✓ Vision service active: ${isActive}`);\n\n // Get vision mode\n const mode = visionService.getVisionMode();\n console.log(`✓ Vision mode: ${mode}`);\n\n // Get enhanced scene description (which uses worker manager if available)\n const scene = await visionService.getEnhancedSceneDescription();\n if (scene) {\n console.log(\"✓ Enhanced scene available\");\n if (scene.screenAnalysis) {\n console.log(\" - Screen analysis present\");\n }\n }\n },\n },\n\n {\n name: \"Should capture screen at high FPS through service\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing high-FPS screen capture through service...\");\n\n const visionService = runtime.getService<VisionService>(\n VisionServiceType.VISION,\n );\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Monitor for 5 seconds\n console.log(\"Monitoring screen capture for 5 seconds...\");\n const startTime = Date.now();\n let frameCount = 0;\n let lastTimestamp = 0;\n\n while (Date.now() - startTime < 5000) {\n const scene = await visionService.getEnhancedSceneDescription();\n if (scene && scene.timestamp !== lastTimestamp) {\n frameCount++;\n lastTimestamp = scene.timestamp;\n }\n\n // Non-blocking check\n await new Promise((resolve) => setImmediate(resolve));\n }\n\n const totalTime = (Date.now() - startTime) / 1000;\n const avgFPS = frameCount / totalTime;\n console.log(\n `✓ Captured ${frameCount} unique frames in ${totalTime.toFixed(2)}s (${avgFPS.toFixed(2)} FPS)`,\n );\n\n if (avgFPS < 1) {\n console.warn(\n \"⚠️ FPS is lower than expected - workers may not be enabled\",\n );\n }\n },\n },\n\n {\n name: \"Should detect quadrant numbers using OCR through service\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing quadrant number detection through service...\");\n\n const visionService = runtime.getService<VisionService>(\n VisionServiceType.VISION,\n );\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Generate test pattern\n const pattern = await generateQuadrantPattern({\n width: 1920,\n height: 1080,\n fontSize: 72,\n includeGrid: true,\n });\n\n const patternPath = await savePattern(pattern, \"quadrant-test.png\");\n console.log(`✓ Test pattern saved to ${patternPath}`);\n\n // Display the pattern\n await displayTestPattern(patternPath);\n\n try {\n // Wait for OCR to process\n console.log(\"Waiting for OCR processing...\");\n await new Promise((resolve) => setTimeout(resolve, 3000));\n\n // Get enhanced scene with OCR results\n const scene = await visionService.getEnhancedSceneDescription();\n const ocrText = scene?.screenAnalysis?.fullScreenOCR || \"\";\n\n console.log(`OCR detected text: \"${ocrText.substring(0, 100)}...\"`);\n\n // Verify quadrant numbers\n const verification = verifyQuadrantNumbers(ocrText);\n console.log(`Found numbers: ${verification.foundNumbers.join(\", \")}`);\n\n if (verification.success) {\n console.log(\"✓ All quadrant numbers detected correctly\");\n } else {\n console.warn(\n `⚠️ Missing numbers: ${verification.missingNumbers.join(\", \")}`,\n );\n }\n\n await closeTestPattern();\n } catch (error) {\n await closeTestPattern();\n throw error;\n }\n },\n },\n\n {\n name: \"Should handle multiple displays through service\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\"Testing multi-display support through service...\");\n\n const visionService = runtime.getService<VisionService>(\n VisionServiceType.VISION,\n );\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Get display count\n const displayCount = await getDisplayCount();\n console.log(`Found ${displayCount} display(s)`);\n\n if (displayCount <= 1) {\n console.log(\"⚠️ Only one display found, skipping multi-display test\");\n return;\n }\n\n // Run for 10 seconds to cycle through displays\n console.log(\"Monitoring displays for 10 seconds...\");\n const startTime = Date.now();\n\n while (Date.now() - startTime < 10000) {\n const scene = await visionService.getEnhancedSceneDescription();\n if (scene?.screenCapture) {\n // Log current screen info\n console.log(\n ` Screen: ${scene.screenCapture.width}x${scene.screenCapture.height}`,\n );\n }\n\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n\n console.log(`✓ Monitored ${displayCount} displays`);\n },\n },\n\n {\n name: \"Should process Florence-2 and OCR in parallel through service\",\n fn: async (runtime: IAgentRuntime) => {\n console.log(\n \"Testing parallel processing performance through service...\",\n );\n\n const visionService = runtime.getService<VisionService>(\n VisionServiceType.VISION,\n );\n if (!visionService) {\n throw new Error(\"Vision service not found\");\n }\n\n // Generate complex pattern\n const pattern = await generateComplexPattern({\n width: 1920,\n height: 1080,\n });\n\n const patternPath = await savePattern(pattern, \"complex-test.png\");\n await displayTestPattern(patternPath);\n\n try {\n // Monitor performance for 10 seconds\n console.log(\"Running parallel processing test for 10 seconds...\");\n const startTime = Date.now();\n const stats = {\n frames: 0,\n ocrDetections: 0,\n florence2Detections: 0,\n };\n\n while (Date.now() - startTime < 10000) {\n const scene = await visionService.getEnhancedSceneDescription();\n\n if (scene) {\n stats.frames++;\n\n if (scene.screenAnalysis?.fullScreenOCR) {\n stats.ocrDetections++;\n }\n\n if (scene.screenAnalysis?.activeTile?.florence2) {\n stats.florence2Detections++;\n }\n }\n\n // Log every 2 seconds\n if ((Date.now() - startTime) % 2000 < 100) {\n console.log(\"\\nCurrent stats:\");\n console.log(` Frames: ${stats.frames}`);\n console.log(` OCR detections: ${stats.ocrDetections}`);\n console.log(\n ` Florence-2 detections: ${stats.florence2Detections}`,\n );\n }\n\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n const totalTime = (Date.now() - startTime) / 1000;\n console.log(\"\\nFinal statistics:\");\n console.log(` Total frames: ${stats.frames}`);\n console.log(\n ` Average FPS: ${(stats.frames / totalTime).toFixed(2)}`,\n );\n console.log(\n ` OCR success rate: ${((stats.ocrDetections / stats.frames) * 100).toFixed(1)}%`,\n );\n console.log(\n ` Florence-2 success rate: ${((stats.florence2Detections / stats.frames) * 100).toFixed(1)}%`,\n );\n\n await closeTestPattern();\n } catch (error) {\n await closeTestPattern();\n throw error;\n }\n },\n },\n ];\n}\n\n// Helper functions\n\nasync function getDisplayCount(): Promise<number> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n const { stdout } = await execAsync(\n \"system_profiler SPDisplaysDataType -json\",\n );\n const data = JSON.parse(stdout);\n return data.SPDisplaysDataType?.[0]?._items?.length || 1;\n } else if (platform === \"linux\") {\n const { stdout } = await execAsync(\n 'xrandr --query | grep \" connected\" | wc -l',\n );\n return parseInt(stdout.trim(), 10) || 1;\n } else if (platform === \"win32\") {\n const { stdout } = await execAsync(\n 'wmic path Win32_DesktopMonitor get DeviceID /format:csv | find /c \"DISPLAY\"',\n );\n return parseInt(stdout.trim(), 10) || 1;\n }\n } catch (error) {\n console.error(\"Failed to get display count:\", error);\n }\n\n return 1;\n}\n\nasync function displayTestPattern(imagePath: string): Promise<void> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // Open in Preview\n await execAsync(`open \"${imagePath}\"`);\n } else if (platform === \"linux\") {\n // Try common image viewers\n try {\n await execAsync(`xdg-open \"${imagePath}\"`);\n } catch {\n await execAsync(`display \"${imagePath}\"`);\n }\n } else if (platform === \"win32\") {\n // Open with default image viewer\n await execAsync(`start \"\" \"${imagePath}\"`);\n }\n\n // Give time for window to open\n await new Promise((resolve) => setTimeout(resolve, 1000));\n } catch (error) {\n console.warn(\"Could not display test pattern:\", error);\n }\n}\n\nasync function closeTestPattern(): Promise<void> {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // Close Preview\n await execAsync(\"osascript -e 'tell application \\\"Preview\\\" to quit'\");\n } else if (platform === \"linux\") {\n // Close common viewers\n await execAsync(\n 'pkill -f \"display.*test-patterns\" || pkill -f \"eog.*test-patterns\" || true',\n );\n } else if (platform === \"win32\") {\n // Close Photos app\n await execAsync(\"taskkill /IM Microsoft.Photos.exe /F 2>nul || exit 0\");\n }\n } catch (_error) {\n // Ignore errors when closing\n }\n}\n\nexport default new VisionWorkerE2ETestSuite();\n",
27
+ "import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { logger } from \"@elizaos/core\";\nimport sharp from \"sharp\";\n\nexport interface TestPatternConfig {\n width: number;\n height: number;\n backgroundColor?: string;\n textColor?: string;\n fontSize?: number;\n includeGrid?: boolean;\n includeTimestamp?: boolean;\n displayIndex?: number;\n}\n\n/**\n * Generate grid lines for the pattern\n */\nfunction generateGrid(\n width: number,\n height: number,\n spacing: number = 100,\n): string {\n const lines: string[] = [];\n\n // Vertical lines\n for (let x = spacing; x < width; x += spacing) {\n lines.push(\n `<line x1=\"${x}\" y1=\"0\" x2=\"${x}\" y2=\"${height}\" stroke=\"#eeeeee\" stroke-width=\"1\"/>`,\n );\n }\n\n // Horizontal lines\n for (let y = spacing; y < height; y += spacing) {\n lines.push(\n `<line x1=\"0\" y1=\"${y}\" x2=\"${width}\" y2=\"${y}\" stroke=\"#eeeeee\" stroke-width=\"1\"/>`,\n );\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Generate a test pattern with numbers in each quadrant and center\n */\nexport async function generateQuadrantPattern(\n config: TestPatternConfig,\n): Promise<Buffer> {\n const {\n width,\n height,\n backgroundColor = \"#ffffff\",\n textColor = \"#000000\",\n fontSize = 48,\n includeGrid = true,\n includeTimestamp = true,\n displayIndex = 0,\n } = config;\n\n // Create SVG with test pattern\n const svg = `\n <svg width=\"${width}\" height=\"${height}\" xmlns=\"http://www.w3.org/2000/svg\">\n <!-- Background -->\n <rect width=\"${width}\" height=\"${height}\" fill=\"${backgroundColor}\"/>\n \n ${includeGrid ? generateGrid(width, height) : \"\"}\n \n <!-- Quadrant dividers -->\n <line x1=\"${width / 2}\" y1=\"0\" x2=\"${width / 2}\" y2=\"${height}\" stroke=\"#cccccc\" stroke-width=\"2\"/>\n <line x1=\"0\" y1=\"${height / 2}\" x2=\"${width}\" y2=\"${height / 2}\" stroke=\"#cccccc\" stroke-width=\"2\"/>\n \n <!-- Quadrant numbers -->\n <text x=\"${width / 4}\" y=\"${height / 4}\" font-family=\"Arial\" font-size=\"${fontSize}\" fill=\"${textColor}\" text-anchor=\"middle\" dominant-baseline=\"middle\">1</text>\n <text x=\"${(3 * width) / 4}\" y=\"${height / 4}\" font-family=\"Arial\" font-size=\"${fontSize}\" fill=\"${textColor}\" text-anchor=\"middle\" dominant-baseline=\"middle\">2</text>\n <text x=\"${width / 4}\" y=\"${(3 * height) / 4}\" font-family=\"Arial\" font-size=\"${fontSize}\" fill=\"${textColor}\" text-anchor=\"middle\" dominant-baseline=\"middle\">3</text>\n <text x=\"${(3 * width) / 4}\" y=\"${(3 * height) / 4}\" font-family=\"Arial\" font-size=\"${fontSize}\" fill=\"${textColor}\" text-anchor=\"middle\" dominant-baseline=\"middle\">4</text>\n \n <!-- Center number -->\n <circle cx=\"${width / 2}\" cy=\"${height / 2}\" r=\"${fontSize}\" fill=\"#ff0000\" opacity=\"0.3\"/>\n <text x=\"${width / 2}\" y=\"${height / 2}\" font-family=\"Arial\" font-size=\"${fontSize}\" fill=\"${textColor}\" text-anchor=\"middle\" dominant-baseline=\"middle\">5</text>\n \n <!-- Display info -->\n <text x=\"20\" y=\"30\" font-family=\"Arial\" font-size=\"16\" fill=\"${textColor}\">Display ${displayIndex}</text>\n <text x=\"20\" y=\"50\" font-family=\"Arial\" font-size=\"16\" fill=\"${textColor}\">${width}x${height}</text>\n \n ${includeTimestamp ? `<text x=\"20\" y=\"70\" font-family=\"Arial\" font-size=\"16\" fill=\"${textColor}\">Time: ${new Date().toISOString()}</text>` : \"\"}\n \n <!-- Corner markers -->\n <circle cx=\"10\" cy=\"10\" r=\"5\" fill=\"#ff0000\"/>\n <circle cx=\"${width - 10}\" cy=\"10\" r=\"5\" fill=\"#00ff00\"/>\n <circle cx=\"10\" cy=\"${height - 10}\" r=\"5\" fill=\"#0000ff\"/>\n <circle cx=\"${width - 10}\" cy=\"${height - 10}\" r=\"5\" fill=\"#ffff00\"/>\n </svg>\n `;\n\n // Convert SVG to PNG\n const buffer = await sharp(Buffer.from(svg)).png().toBuffer();\n\n return buffer;\n}\n\n/**\n * Generate a complex test pattern with multiple text regions\n */\nexport async function generateComplexPattern(\n config: TestPatternConfig,\n): Promise<Buffer> {\n const {\n width,\n height,\n backgroundColor = \"#f0f0f0\",\n textColor = \"#000000\",\n fontSize = 24,\n displayIndex = 0,\n } = config;\n\n // Sample text for OCR testing\n const sampleTexts = [\n \"The quick brown fox jumps over the lazy dog\",\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\",\n \"abcdefghijklmnopqrstuvwxyz\",\n \"0123456789\",\n \"!@#$%^&*()_+-=[]{}|;:,.<>?\",\n ];\n\n const svg = `\n <svg width=\"${width}\" height=\"${height}\" xmlns=\"http://www.w3.org/2000/svg\">\n <!-- Background -->\n <rect width=\"${width}\" height=\"${height}\" fill=\"${backgroundColor}\"/>\n \n <!-- Title -->\n <text x=\"${width / 2}\" y=\"50\" font-family=\"Arial\" font-size=\"32\" fill=\"${textColor}\" text-anchor=\"middle\">Vision Test Pattern - Display ${displayIndex}</text>\n \n <!-- Text regions for OCR testing -->\n ${sampleTexts\n .map(\n (text, i) => `\n <rect x=\"50\" y=\"${150 + i * 80}\" width=\"${width - 100}\" height=\"60\" fill=\"white\" stroke=\"#333\" stroke-width=\"1\"/>\n <text x=\"70\" y=\"${185 + i * 80}\" font-family=\"Arial\" font-size=\"${fontSize}\" fill=\"${textColor}\">${text}</text>\n `,\n )\n .join(\"\")}\n \n <!-- UI Elements -->\n <rect x=\"50\" y=\"${height - 200}\" width=\"150\" height=\"40\" fill=\"#007bff\" rx=\"5\"/>\n <text x=\"125\" y=\"${height - 175}\" font-family=\"Arial\" font-size=\"16\" fill=\"white\" text-anchor=\"middle\">Button</text>\n \n <rect x=\"220\" y=\"${height - 200}\" width=\"200\" height=\"30\" fill=\"white\" stroke=\"#333\" stroke-width=\"1\"/>\n <text x=\"230\" y=\"${height - 180}\" font-family=\"Arial\" font-size=\"14\" fill=\"#666\">Input Field</text>\n \n <!-- Timestamp -->\n <text x=\"${width - 20}\" y=\"${height - 20}\" font-family=\"Arial\" font-size=\"12\" fill=\"#666\" text-anchor=\"end\">${new Date().toISOString()}</text>\n </svg>\n `;\n\n const buffer = await sharp(Buffer.from(svg)).png().toBuffer();\n\n return buffer;\n}\n\n/**\n * Save test pattern to file\n */\nexport async function savePattern(\n buffer: Buffer,\n filename: string,\n): Promise<string> {\n const outputDir = path.join(process.cwd(), \"test-patterns\");\n await fs.mkdir(outputDir, { recursive: true });\n\n const filepath = path.join(outputDir, filename);\n await fs.writeFile(filepath, buffer);\n\n logger.info(`[TestPatternGenerator] Saved test pattern to ${filepath}`);\n return filepath;\n}\n\n/**\n * Generate patterns for all displays\n */\nexport async function generatePatternsForAllDisplays(\n displayCount: number,\n): Promise<Map<number, Buffer>> {\n const patterns = new Map<number, Buffer>();\n\n for (let i = 0; i < displayCount; i++) {\n const pattern = await generateQuadrantPattern({\n width: 1920,\n height: 1080,\n displayIndex: i,\n includeTimestamp: true,\n });\n\n patterns.set(i, pattern);\n }\n\n return patterns;\n}\n\n/**\n * Verify OCR results match expected quadrant numbers\n */\nexport function verifyQuadrantNumbers(ocrText: string): {\n success: boolean;\n foundNumbers: number[];\n missingNumbers: number[];\n} {\n const expectedNumbers = [1, 2, 3, 4, 5];\n const foundNumbers: number[] = [];\n\n // Extract all numbers from OCR text\n const matches = ocrText.match(/\\d+/g);\n if (matches) {\n matches.forEach((match) => {\n const num = parseInt(match, 10);\n if (expectedNumbers.includes(num) && !foundNumbers.includes(num)) {\n foundNumbers.push(num);\n }\n });\n }\n\n const missingNumbers = expectedNumbers.filter(\n (n) => !foundNumbers.includes(n),\n );\n\n return {\n success: missingNumbers.length === 0,\n foundNumbers,\n missingNumbers,\n };\n}\n",
28
+ "// Export all E2E test suites\n\nexport { default as ScreenVisionE2ETestSuite } from \"./screen-vision\";\nexport { default as VisionBasicE2ETestSuite } from \"./vision-basic\";\nexport { default as VisionCaptureLogTestSuite } from \"./vision-capture-log\";\nexport { default as VisionRuntimeTestSuite } from \"./vision-runtime\";\nexport { default as VisionWorkerE2ETestSuite } from \"./vision-worker-tests\";\n\nimport ScreenVisionE2ETestSuite from \"./screen-vision\";\n// Export as array for convenience\nimport VisionBasicE2ETestSuite from \"./vision-basic\";\nimport VisionCaptureLogTestSuite from \"./vision-capture-log\";\nimport VisionRuntimeTestSuite from \"./vision-runtime\";\nimport VisionWorkerE2ETestSuite from \"./vision-worker-tests\";\n\nexport const testSuites = [\n VisionRuntimeTestSuite, // Real runtime tests first\n VisionBasicE2ETestSuite,\n VisionCaptureLogTestSuite,\n ScreenVisionE2ETestSuite,\n VisionWorkerE2ETestSuite, // Worker-based tests\n];\n\nexport default testSuites;\n"
28
29
  ],
29
- "mappings": "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",
30
- "debugId": "08C3A6DFE8F9170A64756E2164756E21",
30
+ "mappings": "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",
31
+ "debugId": "177A2977D034662964756E2164756E21",
31
32
  "names": []
32
33
  }