diff --git a/Data/Agent/borealis-agent.py b/Data/Agent/borealis-agent.py
index 7c10a6c..a09d29d 100644
--- a/Data/Agent/borealis-agent.py
+++ b/Data/Agent/borealis-agent.py
@@ -11,7 +11,8 @@ from PyQt5 import QtCore, QtGui, QtWidgets
from PIL import ImageGrab
# ---------------- Configuration ----------------
-SERVER_URL = "http://localhost:5000" # WebSocket-enabled server URL
+#SERVER_URL = "http://localhost:5000" # WebSocket-enabled Internal URL
+SERVER_URL = "https://borealis.bunny-lab.io" # WebSocket-enabled Public URL"
HOSTNAME = socket.gethostname().lower()
RANDOM_SUFFIX = uuid.uuid4().hex[:8]
@@ -32,7 +33,7 @@ sio = socketio.Client()
# ---------------- WebSocket Handlers ----------------
@sio.event
def connect():
- print(f"[WS CONNECTED] Agent ID: {AGENT_ID} connected to Borealis.")
+ print(f"[WebSocket] Agent ID: {AGENT_ID} connected to Borealis.")
sio.emit('connect_agent', {"agent_id": AGENT_ID, "hostname": HOSTNAME})
sio.emit('request_config', {"agent_id": AGENT_ID})
@@ -123,7 +124,6 @@ class ScreenshotRegion(QtWidgets.QWidget):
# ---------------- Screenshot Capture ----------------
def capture_loop():
- print("[INFO] Screenshot capture loop started")
config_ready.wait()
while region_widget is None:
@@ -172,7 +172,7 @@ if __name__ == "__main__":
app_instance = QtWidgets.QApplication(sys.argv)
region_launcher = RegionLauncher()
- sio.connect(SERVER_URL)
+ sio.connect(SERVER_URL, transports=['websocket'])
threading.Thread(target=capture_loop, daemon=True).start()
diff --git a/Data/Agent/requirements.txt b/Data/Agent/requirements.txt
index 883322d..3cf8ec0 100644
--- a/Data/Agent/requirements.txt
+++ b/Data/Agent/requirements.txt
@@ -1,3 +1,10 @@
+# API / WebSocket Handling
requests
+python-socketio
+websocket-client
+
+# GUI-related dependencies (Qt for GUI components)
PyQt5
-Pillow
+
+# Computer Vision & OCR Dependencies
+Pillow
\ No newline at end of file
diff --git a/Data/WebUI/src/nodes/Agent/Node_Borealis_Agent.jsx b/Data/WebUI/src/nodes/Agent/Node_Borealis_Agent.jsx
index 08b67a5..2478b37 100644
--- a/Data/WebUI/src/nodes/Agent/Node_Borealis_Agent.jsx
+++ b/Data/WebUI/src/nodes/Agent/Node_Borealis_Agent.jsx
@@ -2,9 +2,11 @@ import React, { useEffect, useState, useRef } from "react";
import { Handle, Position, useReactFlow } from "reactflow";
import { io } from "socket.io-client";
-const socket = io();
+const socket = io(window.location.origin, {
+ transports: ["websocket"]
+});
-const APINode = ({ id, data }) => {
+const BorealisAgentNode = ({ id, data }) => {
const { setNodes } = useReactFlow();
const [agents, setAgents] = useState([]);
const [selectedAgent, setSelectedAgent] = useState(data.agent_id || "");
@@ -13,6 +15,7 @@ const APINode = ({ id, data }) => {
const [paused, setPaused] = useState(false);
const [overlayVisible, setOverlayVisible] = useState(true);
const [imageData, setImageData] = useState("");
+ const imageRef = useRef("");
useEffect(() => {
fetch("/api/agents").then(res => res.json()).then(setAgents);
@@ -24,15 +27,39 @@ const APINode = ({ id, data }) => {
useEffect(() => {
socket.on('new_screenshot', (data) => {
+ console.log("[DEBUG] Screenshot received", data);
if (data.agent_id === selectedAgent) {
setImageData(data.image_base64);
- window.BorealisValueBus = window.BorealisValueBus || {};
- window.BorealisValueBus[id] = data.image_base64;
+ imageRef.current = data.image_base64;
}
});
return () => socket.off('new_screenshot');
- }, [selectedAgent, id]);
+ }, [selectedAgent]);
+
+ useEffect(() => {
+ const interval = setInterval(() => {
+ if (!paused && imageRef.current) {
+ window.BorealisValueBus = window.BorealisValueBus || {};
+ window.BorealisValueBus[id] = imageRef.current;
+
+ setNodes(nds => {
+ const updated = [...nds];
+ const node = updated.find(n => n.id === id);
+ if (node) {
+ node.data = {
+ ...node.data,
+ value: imageRef.current
+ };
+ }
+ return updated;
+ });
+
+ }
+ }, window.BorealisUpdateRate || 100);
+
+ return () => clearInterval(interval);
+ }, [id, paused, setNodes]);
const provisionAgent = () => {
if (!selectedAgent) return;
@@ -49,18 +76,11 @@ const APINode = ({ id, data }) => {
visible: overlayVisible,
task: selectedType
})
- }).then(() => {
- socket.emit('request_config', { agent_id: selectedAgent });
- setNodes(nds =>
- nds.map(n => n.id === id
- ? {
- ...n,
- data: { agent_id: selectedAgent, data_type: selectedType, interval: intervalMs }
- }
- : n
- )
- );
- });
+ })
+ .then(res => res.json())
+ .then(() => {
+ console.log("[DEBUG] Agent provisioned");
+ });
};
const toggleOverlay = () => {
@@ -72,7 +92,7 @@ const APINode = ({ id, data }) => {
return (
-
API Data Collector
+
Borealis Agent