osamabyc86 commited on
Commit
58ad27b
·
verified ·
1 Parent(s): 2e17a1b

Upload 66 files

Browse files
DeviceManager.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import GPUtil
3
+ import psutil
4
+ import logging
5
+ from peer_discovery import PORT
6
+
7
+ logging.getLogger().setLevel(logging.CRITICAL) # صامت
8
+
9
+ class DeviceManager:
10
+ def __init__(self):
11
+ self.devices = {
12
+ "GPU": self._detect_gpus(),
13
+ "DSP": self._detect_dsps(),
14
+ "NIC": self._detect_nics(),
15
+ "STORAGE": self._detect_storage(),
16
+ "CAPTURE": self._detect_capture(),
17
+ "ACCELERATOR": self._detect_accelerators()
18
+ }
19
+
20
+ # ────────────── اكتشاف الكروت ──────────────
21
+ def _detect_gpus(self):
22
+ try:
23
+ return GPUtil.getGPUs()
24
+ except:
25
+ return []
26
+
27
+ def _detect_dsps(self):
28
+ try:
29
+ output = subprocess.check_output(["aplay", "-l"], stderr=subprocess.DEVNULL).decode()
30
+ return ["DSP_Audio"] if "card" in output.lower() else []
31
+ except:
32
+ return []
33
+
34
+ def _detect_nics(self):
35
+ try:
36
+ return list(psutil.net_if_addrs().keys())
37
+ except:
38
+ return []
39
+
40
+ def _detect_storage(self):
41
+ try:
42
+ output = subprocess.check_output(["lsblk", "-o", "NAME"], stderr=subprocess.DEVNULL).decode()
43
+ return output.split() if output else []
44
+ except:
45
+ return []
46
+
47
+ def _detect_capture(self):
48
+ try:
49
+ output = subprocess.check_output(["v4l2-ctl", "--list-devices"], stderr=subprocess.DEVNULL).decode()
50
+ return output.split(":")[0::2] if output else []
51
+ except:
52
+ return []
53
+
54
+ def _detect_accelerators(self):
55
+ # افتراض: في المستقبل يمكن إضافة اكتشاف حقيقي لـ FPGA/TPU
56
+ return []
57
+
58
+ # ────────────── فحص الحمل ──────────────
59
+ def get_device_load(self, device_type, index=0):
60
+ try:
61
+ if device_type == "GPU" and self.devices["GPU"]:
62
+ return self.devices["GPU"][index].load * 100
63
+ elif device_type == "DSP" and self.devices["DSP"]:
64
+ return 10 # افتراضي: ما في API للحمل
65
+ elif device_type == "NIC" and self.devices["NIC"]:
66
+ return psutil.net_io_counters().bytes_sent / (1024 * 1024) # مثال بسيط
67
+ elif device_type == "STORAGE" and self.devices["STORAGE"]:
68
+ return psutil.disk_usage('/').percent
69
+ elif device_type == "CAPTURE" and self.devices["CAPTURE"]:
70
+ return 20 # افتراضي: حمل منخفض
71
+ elif device_type == "ACCELERATOR" and self.devices["ACCELERATOR"]:
72
+ return 15 # افتراضي
73
+ return 0
74
+ except:
75
+ return 0
76
+
77
+ # ────────────── منطق 30% / 70% ──────────────
78
+ def can_receive(self, device_type, index=0):
79
+ return self.get_device_load(device_type, index) <= 30
80
+
81
+ def should_offload(self, device_type, index=0):
82
+ return self.get_device_load(device_type, index) >= 70
New Text Document.txt ADDED
File without changes
README_FIXES.md ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # AmalOffload v6 — Fix Pack
2
+
3
+ تم إنشاء نسخة مُرقّعة من المشروع مع إصلاحات أساسية تمنع الأعطال الفورية وتسهّل التشغيل.
4
+
5
+ ## ما الذي تم إصلاحه؟
6
+ - autostart_config.py: dedup import of PORT
7
+ - background_service.py: dedup import of PORT
8
+ - central_manager.py: dedup import of PORT
9
+ - control.py: dedup import of PORT
10
+ - dashboard.py: dedup import of PORT
11
+ - DeviceManager.py: dedup import of PORT
12
+ - distributed_executor.py: dedup import of PORT
13
+ - dts_cli.py: dedup import of PORT
14
+ - enhanced_assistant.py: dedup import of PORT
15
+ - external_server.py: dedup import of PORT
16
+ - internet_scanner.py: dedup import of PORT
17
+ - launcher.py: dedup import of PORT
18
+ - live_streaming.py: dedup import of PORT
19
+ - load_balancer.py: dedup import of PORT
20
+ - peer_registry.py: dedup import of PORT
21
+ - peer_server.py: dedup import of PORT
22
+ - remote_executor.py: dedup import of PORT
23
+ - rpc_server.py: dedup import of PORT
24
+ - security_layer.py: dedup import of PORT
25
+ - server.py: dedup import of PORT
26
+ - smart_tasks.py: dedup import of PORT
27
+ - system_check.py: dedup import of PORT
28
+ - system_tray.py: dedup import of PORT
29
+ - task_splitter.py: dedup import of PORT
30
+ - test_distributed_system.py: dedup import of PORT
31
+ - test_monitor.py: dedup import of PORT
32
+ - video_processing.py: dedup import of PORT
33
+ - your_tasks.py: dedup import of PORT
34
+ - control.py: fixed broken import line
35
+ - dts_cli.py: rewritten to a minimal, valid CLI
36
+ - ram_manager.py: removed BOM
37
+ - templates/dashboard.html: created from index.html
38
+ - config.py: added as a single source of truth for PORT
39
+
40
+ ## توصيات إضافية (يدويّة)
41
+ - أضِف `fastapi` و`uvicorn` إلى `requirements.txt` إذا أردت تشغيل `central_manager.py` (يستخدم FastAPI).
42
+ - وحّد استيراد المنفذ عبر:
43
+ ```python
44
+ from config import PORT
45
+ ```
46
+ واستبدل أي استخدام لـ `from peer_discovery import PORT, PORT` أو `CPU_PORT` حسب الحاجة.
47
+ - إن ظهرت مشكلة `TemplateNotFound: dashboard.html` فقد تم إنشاء `templates/dashboard.html` تلقائياً.
48
+ - يُفضّل تنظيف `requirements.txt` من التكرارات (انظر التوصيات في تقرير التدقيق).
49
+ - اختر نقطة دخول واحدة للمشروع (مثلاً: `launcher.py` أو `startup.py`) وتجنّب تشغيل أكثر من خادم في نفس العملية.
50
+
51
+ ## التشغيل السريع المقترح
52
+ 1) ثبّت المتطلبات (الأساسية فقط):
53
+ ```bash
54
+ pip install flask flask_cors flask_socketio requests psutil zeroconf cryptography numpy networkx GPUtil python-dotenv
55
+ ```
56
+ 2) شغّل الـ Dashboard وخادم RPC معاً:
57
+ ```bash
58
+ python dts_cli.py start
59
+ ```
60
+
61
+ بالتوفيق!
auto_offload.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import torch
3
+ import GPUtil
4
+ import psutil
5
+ import logging
6
+
7
+ logging.getLogger().setLevel(logging.CRITICAL) # صامت تمامًا
8
+
9
+ class DeviceManager:
10
+ def __init__(self):
11
+ self.gpus = self._detect_gpus()
12
+ self.dsps = self._detect_dsps()
13
+ # في المستقبل يمكن إضافة كروت أخرى بنفس النمط
14
+
15
+ def _detect_gpus(self):
16
+ """اكتشاف جميع الـ GPUs المتاحة"""
17
+ try:
18
+ return GPUtil.getGPUs()
19
+ except Exception:
20
+ return []
21
+
22
+ def _detect_dsps(self):
23
+ """تحقق من وجود DSP أو كروت صوتية"""
24
+ try:
25
+ output = subprocess.check_output(["aplay", "-l"], stderr=subprocess.DEVNULL).decode()
26
+ if "card" in output.lower():
27
+ return ["DSP_Audio"]
28
+ return []
29
+ except Exception:
30
+ return []
31
+
32
+ def get_device_load(self, device_type, index=0):
33
+ """إرجاع نسبة الحمل للجهاز"""
34
+ if device_type == "GPU" and self.gpus:
35
+ try:
36
+ return self.gpus[index].load * 100 # نسبة مئوية
37
+ except Exception:
38
+ return 0
39
+ elif device_type == "DSP" and self.dsps:
40
+ # هنا ما في API رسمية، نفترض DSP قليل الحمل دائمًا كمثال
41
+ return 10
42
+ return 0
43
+
44
+ class AutoOffloadExecutor:
45
+ def __init__(self, executor):
46
+ self.executor = executor
47
+ self.devices = DeviceManager()
48
+
49
+ def _should_offload(self, device_type, index=0):
50
+ load = self.devices.get_device_load(device_type, index)
51
+ return load >= 70
52
+
53
+ def _can_receive(self, device_type, index=0):
54
+ load = self.devices.get_device_load(device_type, index)
55
+ return load <= 30
56
+
57
+ def submit_auto(self, task_func, *args, task_type=None, **kwargs):
58
+ """إرسال تلقائي حسب حالة الكروت"""
59
+ device_type = "CPU" # افتراضي
60
+ if task_type == "video" and self.devices.gpus:
61
+ device_type = "GPU"
62
+ elif task_type == "audio" and self.devices.dsps:
63
+ device_type = "DSP"
64
+
65
+ if self._should_offload(device_type):
66
+ # حمل عالي → أرسل
67
+ self.executor.submit(task_func, *args, **kwargs)
68
+ elif self._can_receive(device_type):
69
+ # حمل منخفض → نفذ محليًا
70
+ task_func(*args, **kwargs)
71
+ else:
72
+ # حمل متوسط → نفذ محليًا
73
+ task_func(*args, **kwargs)
autostart_config.py CHANGED
@@ -2,6 +2,7 @@ import json
2
  import os
3
  import platform
4
  from pathlib import Path
 
5
 
6
  class AutoStartManager:
7
  def __init__(self, app_name="DistributedTaskSystem"):
 
2
  import os
3
  import platform
4
  from pathlib import Path
5
+ from peer_discovery import PORT
6
 
7
  class AutoStartManager:
8
  def __init__(self, app_name="DistributedTaskSystem"):
background_service.py CHANGED
@@ -16,6 +16,7 @@ from pathlib import Path
16
  from flask import Flask, jsonify, request
17
  import json
18
  from datetime import datetime
 
19
 
20
  class BackgroundService:
21
  def __init__(self):
 
16
  from flask import Flask, jsonify, request
17
  import json
18
  from datetime import datetime
19
+ from peer_discovery import PORT
20
 
21
  class BackgroundService:
22
  def __init__(self):
briefcase ADDED
File without changes
central_manager.py CHANGED
@@ -8,6 +8,7 @@ from typing import Dict, List
8
  import requests
9
  from fastapi import FastAPI, HTTPException
10
  from pydantic import BaseModel
 
11
 
12
  # ---- إعداد FastAPI ----------------------------------------------------------
13
  app = FastAPI(title="Central Task Manager")
@@ -16,7 +17,7 @@ app = FastAPI(title="Central Task Manager")
16
 
17
  class RegisterRequest(BaseModel):
18
  """تسجيل أو تجديد ظهور العقدة."""
19
- url: str # مثلاً: "http://203.0.113.45:7520/run"
20
  load: float = 0.0 # نسبة تحميل العقدة (0.0 - 1.0)، اختياري
21
 
22
  class TaskRequest(BaseModel):
 
8
  import requests
9
  from fastapi import FastAPI, HTTPException
10
  from pydantic import BaseModel
11
+ from peer_discovery import PORT
12
 
13
  # ---- إعداد FastAPI ----------------------------------------------------------
14
  app = FastAPI(title="Central Task Manager")
 
17
 
18
  class RegisterRequest(BaseModel):
19
  """تسجيل أو تجديد ظهور العقدة."""
20
+ url: str # مثلاً: "http://203.0.113.45:PORT/run"
21
  load: float = 0.0 # نسبة تحميل العقدة (0.0 - 1.0)، اختياري
22
 
23
  class TaskRequest(BaseModel):
config.py CHANGED
@@ -1,10 +1,7 @@
1
- # config.py
 
2
 
3
- OPENAI_API_KEY = "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"
4
-
5
- DEFAULT_LANGUAGE = "ar"
6
- DEFAULT_MODEL = "gpt-4"
7
- SYSTEM_PROMPT = """
8
- أنت مساعد ذكاء اصطناعي يتحكم به المستخدم عبر أوامر صوتية وكتابية،
9
- يجب أن تستجيب بسرعة، وبدقة، وتتعلم من التعليمات الجديدة.
10
- """
 
1
+ # config.py — نقطة مركزية لإعدادات المشروع
2
+ import os, random
3
 
4
+ # مصدر الحقيقة الوحيد لمنفذ الخدمة
5
+ PORT = int(os.getenv("CPU_PORT", os.getenv("PORT", "0")))
6
+ if PORT == 0:
7
+ PORT = random.randint(5000, 9999)
 
 
 
 
dashboard.py CHANGED
@@ -1,55 +1,60 @@
1
- # dashboard.py
2
- from flask import Flask, render_template, jsonify
3
- from peer_discovery import discover_peers
4
- import threading
5
- import time
6
- from typing import List, Dict
7
  import logging
 
 
 
 
 
 
 
 
8
 
9
- app = Flask(__name__)
10
- app.logger.setLevel(logging.INFO)
11
 
12
- # تهيئة قائمة الأقران
13
- current_peers: Dict[str, List[Dict[str, str]]] = {"local": [], "external": []}
14
 
15
- def update_peers_loop() -> None:
16
- """حلقة تحديث قائمة الأقران بشكل دوري"""
17
- global current_peers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  while True:
19
- try:
20
- new_peers = discover_peers()
21
- current_peers = new_peers
22
- total_peers = len(new_peers["local"]) + len(new_peers["external"])
23
- app.logger.info(f"تم تحديث قائمة الأقران: {total_peers} جهاز")
24
- except Exception as e:
25
- app.logger.error(f"خطأ في اكتشاف الأقران: {str(e)}")
26
- time.sleep(10)
27
 
 
28
  @app.route("/")
29
- def dashboard() -> str:
30
- """عرض لوحة التحكم الرئيسية"""
31
- total_peers = len(current_peers["local"]) + len(current_peers["external"])
32
- return render_template("dashboard.html",
33
- peers_count=total_peers,
34
- last_update=time.strftime("%Y-%m-%d %H:%M:%S"))
35
-
36
- @app.route("/api/peers")
37
- def get_peers() -> dict:
38
- """واجهة API للحصول على قائمة الأقران"""
39
- total_peers = len(current_peers["local"]) + len(current_peers["external"])
40
- return jsonify({
41
- "peers": current_peers,
42
- "count": total_peers,
43
- "status": "success"
44
- })
45
-
46
- def start_background_thread() -> None:
47
- """بدء خيط الخلفية لتحديث الأقران"""
48
- thread = threading.Thread(target=update_peers_loop)
49
- thread.daemon = True
50
- thread.start()
51
 
52
- if __name__ == "__main__":
53
- start_background_thread()
54
- app.run(host="0.0.0.0", port=7530, debug=False)
 
 
 
 
 
 
 
55
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import logging
2
+ import socket
3
+ import threading
4
+ import psutil
5
+ import GPUtil
6
+ from flask import Flask, render_template
7
+ from flask_socketio import SocketIO, emit
8
+ from peer_discovery import PEERS
9
+ from peer_discovery import PORT
10
 
 
 
11
 
12
+ logging.basicConfig(level=logging.INFO)
 
13
 
14
+ app = Flask(__name__)
15
+ socketio = SocketIO(app, cors_allowed_origins="*")
16
+
17
+ node_id = socket.gethostname()
18
+ connected_peers_data = {}
19
+
20
+ # ─────────────── جمع بيانات الحمل ───────────────
21
+ def get_system_status():
22
+ cpu = psutil.cpu_percent()
23
+ ram = psutil.virtual_memory().percent
24
+ gpu_load = 0
25
+ try:
26
+ gpus = GPUtil.getGPUs()
27
+ if gpus:
28
+ gpu_load = gpus[0].load * 100
29
+ except:
30
+ pass
31
+ return {"cpu": cpu, "ram": ram, "gpu": gpu_load}
32
+
33
+ # ─────────────── إرسال التحديثات ───────────────
34
+ def broadcast_status():
35
  while True:
36
+ status = get_system_status()
37
+ socketio.emit("status_update", {node_id: status}, broadcast=True)
38
+ socketio.sleep(5)
 
 
 
 
 
39
 
40
+ # ─────────────── صفحة الواجهة ───────────────
41
  @app.route("/")
42
+ def index():
43
+ return render_template("dashboard.html", peers=connected_peers_data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
+ # ─────────────── استقبال تحديثات الحالة ───────────────
46
+ @socketio.on("status_update")
47
+ def handle_status_update(data):
48
+ connected_peers_data.update(data)
49
+ emit("update_peers", connected_peers_data, broadcast=True)
50
+
51
+ # ─────────────── دردشة ───────────────
52
+ @socketio.on("send_message")
53
+ def handle_message(data):
54
+ emit("receive_message", data, broadcast=True)
55
 
56
+ # ─────────────── تشغيل ───────────────
57
+ if __name__ == "__main__":
58
+ threading.Thread(target=broadcast_status).start()
59
+ logging.info(f"🚀 تشغيل Dashboard على {node_id}")
60
+ socketio.run(app, host="0.0.0.0", port=7000)
distributed_executor.py CHANGED
@@ -1,15 +1,97 @@
1
  import threading
2
  import queue
3
  import time
4
- import json
5
  from typing import Callable, Dict, List
6
  import socket
7
  from zeroconf import Zeroconf, ServiceBrowser, ServiceInfo
8
  import logging
9
  import requests
 
 
 
 
 
 
10
 
11
  logging.basicConfig(level=logging.INFO)
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  class PeerRegistry:
14
  def __init__(self):
15
  self._peers = {}
@@ -60,7 +142,7 @@ class PeerRegistry:
60
  self.add_service(zc, type_, name)
61
 
62
  def remove_service(self, zc, type_, name):
63
- pass # يمكن تحسينه لاحقًا
64
 
65
  listener = Listener()
66
  ServiceBrowser(self._zeroconf, "_tasknode._tcp.local.", listener)
@@ -78,7 +160,7 @@ class PeerRegistry:
78
  s.close()
79
  return ip
80
 
81
-
82
  class DistributedExecutor:
83
  def __init__(self, shared_secret: str):
84
  self.peer_registry = PeerRegistry()
@@ -86,6 +168,7 @@ class DistributedExecutor:
86
  self.task_queue = queue.PriorityQueue()
87
  self.result_cache = {}
88
  self.available_peers = []
 
89
  self._init_peer_discovery()
90
 
91
  def _init_peer_discovery(self):
@@ -97,7 +180,26 @@ class DistributedExecutor:
97
 
98
  threading.Thread(target=discovery_loop, daemon=True).start()
99
 
100
- def submit(self, task_func: Callable, *args, **kwargs):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  task_id = f"{task_func.__name__}_{time.time()}"
102
 
103
  task = {
@@ -122,6 +224,7 @@ class DistributedExecutor:
122
  self._send_to_peer(peer, task)
123
  else:
124
  logging.warning("⚠️ لا توجد أجهزة متاحة - سيتم تنفيذ المهمة محلياً")
 
125
 
126
  def _is_local_ip(self, ip: str) -> bool:
127
  return (
@@ -142,14 +245,13 @@ class DistributedExecutor:
142
  logging.error(f"❌ فشل إرسال المهمة لـ {peer['node_id']}: {e}")
143
  return None
144
 
145
-
146
  if __name__ == "__main__":
147
  executor = DistributedExecutor("my_secret_key")
148
- executor.peer_registry.register_service("node1", 7520, load=0.1)
149
  print("✅ نظام توزيع المهام جاهز...")
150
 
151
  def example_task(x):
152
  return x * x
153
 
154
- executor.submit(example_task, 5)
155
-
 
1
  import threading
2
  import queue
3
  import time
 
4
  from typing import Callable, Dict, List
5
  import socket
6
  from zeroconf import Zeroconf, ServiceBrowser, ServiceInfo
7
  import logging
8
  import requests
9
+ import subprocess
10
+ import psutil
11
+ import GPUtil
12
+ from processor_manager import ResourceMonitor
13
+ from peer_discovery import PORT
14
+
15
 
16
  logging.basicConfig(level=logging.INFO)
17
 
18
+ # ─────────────── Device Manager عام ───────────────
19
+ class DeviceManager:
20
+ def __init__(self):
21
+ self.devices = {
22
+ "GPU": self._detect_gpus(),
23
+ "DSP": self._detect_dsps(),
24
+ "NIC": self._detect_nics(),
25
+ "STORAGE": self._detect_storage(),
26
+ "CAPTURE": self._detect_capture(),
27
+ "ACCELERATOR": self._detect_accelerators()
28
+ }
29
+
30
+ # اكتشاف الأجهزة
31
+ def _detect_gpus(self):
32
+ try:
33
+ return GPUtil.getGPUs()
34
+ except:
35
+ return []
36
+
37
+ def _detect_dsps(self):
38
+ try:
39
+ output = subprocess.check_output(["aplay", "-l"], stderr=subprocess.DEVNULL).decode()
40
+ return ["DSP_Audio"] if "card" in output.lower() else []
41
+ except:
42
+ return []
43
+
44
+ def _detect_nics(self):
45
+ try:
46
+ return list(psutil.net_if_addrs().keys())
47
+ except:
48
+ return []
49
+
50
+ def _detect_storage(self):
51
+ try:
52
+ output = subprocess.check_output(["lsblk", "-o", "NAME"], stderr=subprocess.DEVNULL).decode()
53
+ return output.split() if output else []
54
+ except:
55
+ return []
56
+
57
+ def _detect_capture(self):
58
+ try:
59
+ output = subprocess.check_output(["v4l2-ctl", "--list-devices"], stderr=subprocess.DEVNULL).decode()
60
+ return output.split(":")[0::2] if output else []
61
+ except:
62
+ return []
63
+
64
+ def _detect_accelerators(self):
65
+ # افتراضي: يمكن إضافة اكتشاف حقيقي مستقبلاً
66
+ return ["Accelerator_Device"]
67
+
68
+ # قياس الحمل
69
+ def get_device_load(self, device_type, index=0):
70
+ try:
71
+ if device_type == "GPU" and self.devices["GPU"]:
72
+ return self.devices["GPU"][index].load * 100
73
+ elif device_type == "DSP" and self.devices["DSP"]:
74
+ return 10 # افتراضي
75
+ elif device_type == "NIC" and self.devices["NIC"]:
76
+ return psutil.net_io_counters().bytes_sent / (1024 * 1024) # MB sent كمثال
77
+ elif device_type == "STORAGE" and self.devices["STORAGE"]:
78
+ return psutil.disk_usage('/').percent
79
+ elif device_type == "CAPTURE" and self.devices["CAPTURE"]:
80
+ return 20 # افتراضي
81
+ elif device_type == "ACCELERATOR" and self.devices["ACCELERATOR"]:
82
+ return 15 # افتراضي
83
+ return 0
84
+ except:
85
+ return 0
86
+
87
+ # منطق الاستقبال/الإرسال
88
+ def can_receive(self, device_type, index=0):
89
+ return self.get_device_load(device_type, index) <= 30
90
+
91
+ def should_offload(self, device_type, index=0):
92
+ return self.get_device_load(device_type, index) >= 70
93
+
94
+ # ─────────────── Peer Registry ───────────────
95
  class PeerRegistry:
96
  def __init__(self):
97
  self._peers = {}
 
142
  self.add_service(zc, type_, name)
143
 
144
  def remove_service(self, zc, type_, name):
145
+ pass
146
 
147
  listener = Listener()
148
  ServiceBrowser(self._zeroconf, "_tasknode._tcp.local.", listener)
 
160
  s.close()
161
  return ip
162
 
163
+ # ─────────────── Distributed Executor ───────────────
164
  class DistributedExecutor:
165
  def __init__(self, shared_secret: str):
166
  self.peer_registry = PeerRegistry()
 
168
  self.task_queue = queue.PriorityQueue()
169
  self.result_cache = {}
170
  self.available_peers = []
171
+ self.devices = DeviceManager()
172
  self._init_peer_discovery()
173
 
174
  def _init_peer_discovery(self):
 
180
 
181
  threading.Thread(target=discovery_loop, daemon=True).start()
182
 
183
+ def submit(self, task_func: Callable, *args, task_type=None, **kwargs):
184
+ monitor = ResourceMonitor().current_load()
185
+ avg_cpu = monitor["average"]["cpu"]
186
+ avg_mem = monitor["average"]["mem_percent"] if "mem_percent" in monitor["average"] else 0
187
+
188
+ # تحديد نوع الجهاز
189
+ device_type = task_type.upper() if task_type else "CPU"
190
+
191
+ # فحص الحمل
192
+ if (avg_cpu > 0.6 or avg_mem > 85 or self.devices.should_offload(device_type)):
193
+ logging.info(f"⚠️ الحمل مرتفع على {device_type} - إرسال المهمة للأقران")
194
+ self._offload_task(task_func, *args, **kwargs)
195
+ elif (avg_cpu <= 0.3 and self.devices.can_receive(device_type)):
196
+ logging.info(f"✅ الحمل منخفض على {device_type} - تنفيذ المهمة محلياً")
197
+ return task_func(*args, **kwargs)
198
+ else:
199
+ logging.info(f"ℹ️ الحمل متوسط على {device_type} - تنفيذ المهمة محلياً")
200
+ return task_func(*args, **kwargs)
201
+
202
+ def _offload_task(self, task_func: Callable, *args, **kwargs):
203
  task_id = f"{task_func.__name__}_{time.time()}"
204
 
205
  task = {
 
224
  self._send_to_peer(peer, task)
225
  else:
226
  logging.warning("⚠️ لا توجد أجهزة متاحة - سيتم تنفيذ المهمة محلياً")
227
+ task_func(*args, **kwargs)
228
 
229
  def _is_local_ip(self, ip: str) -> bool:
230
  return (
 
245
  logging.error(f"❌ فشل إرسال المهمة لـ {peer['node_id']}: {e}")
246
  return None
247
 
248
+ # ─────────────── تشغيل رئيسي ───────────────
249
  if __name__ == "__main__":
250
  executor = DistributedExecutor("my_secret_key")
251
+ executor.peer_registry.register_service("node1", PORT, load=0.1)
252
  print("✅ نظام توزيع المهام جاهز...")
253
 
254
  def example_task(x):
255
  return x * x
256
 
257
+ executor.submit(example_task, 5, task_type="GPU")
 
dts_cli.py CHANGED
@@ -1,8 +1,9 @@
1
- # dts_cli.py
2
  import click
3
- from dashboard import app
4
- from rpc_server import app as rpc_app
5
  import threading
 
 
 
6
 
7
  @click.group()
8
  def cli():
@@ -10,56 +11,17 @@ def cli():
10
 
11
  @cli.command()
12
  def start():
13
- """بدء النظام الموزع"""
14
- print("جارِ تشغيل النظام الموزع...")
15
-
16
- # تشغيل واجهة التحكم في خيط منفصل
17
- dashboard_thread = threading.Thread(
18
- target=lambda: app.run(host="0.0.0.0", port=5000)
19
- )
20
- dashboard_thread.daemon = True
21
- dashboard_thread.start()
22
-
23
- # تشغيل خادم RPC
24
- rpc_app.run(host="0.0.0.0", port=7520)
25
 
26
  @cli.command()
27
- from flask import Flask, render_template, request
28
-
29
- # ... (الكود الحالي)
30
-
31
- @flask_app.route("/")
32
- def home():
33
- tasks = {
34
- "1": ("ضرب المصفوفات", "matrix"),
35
- "2": ("حساب الأعداد الأولية", "prime"),
36
- "3": ("معالجة البيانات", "data"),
37
- }
38
- return render_template("index.html", tasks=tasks)
39
-
40
- @flask_app.route("/run_task", methods=["POST"])
41
- def run_task():
42
- task_id = request.form.get("task_id")
43
- result = None
44
-
45
- if task_id == "1":
46
- result = matrix_multiply(500) # استبدل بمعاملاتك الفعلية
47
- elif task_id == "2":
48
- result = prime_calculation(100_000)
49
- elif task_id == "3":
50
- result = data_processing(10_000)
51
-
52
- return render_template("index.html", tasks={
53
- "1": ("ضرب المصفوفات", "matrix"),
54
- "2": ("حساب الأعداد الأولية", "prime"),
55
- "3": ("معالجة البيانات", "data"),
56
- }, result=result)
57
  def discover():
58
- """عرض الأجهزة المتصلة"""
59
- from peer_discovery import discover_peers
60
- peers = discover_peers()
61
- print("الأجهزة المتصلة:")
62
- for i, peer in enumerate(peers, 1):
63
  print(f"{i}. {peer}")
64
 
65
  if __name__ == "__main__":
 
1
+ # dts_cli.py — أوامر CLI لتشغيل النظام الموزع
2
  import click
 
 
3
  import threading
4
+ from peer_discovery import PEERS, PORT
5
+ import dashboard
6
+ import rpc_server
7
 
8
  @click.group()
9
  def cli():
 
11
 
12
  @cli.command()
13
  def start():
14
+ """بدء Dashboard وخادم RPC معاً"""
15
+ # شغّل الـ Dashboard في خيط منفصل
16
+ t = threading.Thread(target=lambda: dashboard.socketio.run(dashboard.app, host="0.0.0.0", port=7000), daemon=True)
17
+ t.start()
18
+ # شغّل خادم RPC في الخيط الرئيسي
19
+ rpc_server.app.run(host="0.0.0.0", port=PORT)
 
 
 
 
 
 
20
 
21
  @cli.command()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  def discover():
23
+ """طباعة قائمة الأقران المكتشفة"""
24
+ for i, peer in enumerate(sorted(PEERS), 1):
 
 
 
25
  print(f"{i}. {peer}")
26
 
27
  if __name__ == "__main__":
enhanced_assistant.py CHANGED
@@ -9,6 +9,7 @@ from PIL import Image
9
  from io import BytesIO
10
  import re
11
  from datetime import datetime
 
12
 
13
  class EnhancedNoraAssistant:
14
  def __init__(self):
 
9
  from io import BytesIO
10
  import re
11
  from datetime import datetime
12
+ from peer_discovery import PORT
13
 
14
  class EnhancedNoraAssistant:
15
  def __init__(self):
external_server.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ external_server.py — سيرفر مركزي لتوزيع المهام + Dashboard تفاعلي
4
+ """
5
+ import logging
6
+ import requests
7
+ from flask import Flask, request, jsonify, render_template
8
+ from flask_cors import CORS
9
+ from flask_socketio import SocketIO, emit
10
+ from peer_discovery import PEERS
11
+ from peer_discovery import PORT
12
+
13
+ logging.basicConfig(level=logging.INFO)
14
+
15
+ app = Flask(__name__)
16
+ CORS(app, resources={r"/*": {"origins": "*"}})
17
+ socketio = SocketIO(app, cors_allowed_origins="*")
18
+
19
+ connected_peers = {} # {node_id: {"cpu":%, "ram":%, "gpu":%}}
20
+
21
+ # ─────────────── اختيار أفضل Peer ───────────────
22
+ def select_best_peer():
23
+ peers_list = list(PEERS)
24
+ if not peers_list:
25
+ logging.warning("⚠️ لا توجد أجهزة مسجلة حالياً.")
26
+ return None
27
+
28
+ try:
29
+ peer_loads = []
30
+ for peer_url in peers_list:
31
+ try:
32
+ resp = requests.get(f"{peer_url.replace('/run_task','')}/status", timeout=2)
33
+ if resp.ok:
34
+ data = resp.json()
35
+ peer_loads.append((peer_url, data.get("cpu_load", 100)))
36
+ except:
37
+ continue
38
+
39
+ if not peer_loads:
40
+ return None
41
+
42
+ peer_loads.sort(key=lambda x: x[1])
43
+ return peer_loads[0][0]
44
+ except Exception as e:
45
+ logging.error(f"❌ خطأ في اختيار الـ Peer: {e}")
46
+ return None
47
+
48
+ # ─────────────── API توزيع المهام ───────────────
49
+ @app.route("/submit_task", methods=["POST"])
50
+ def submit_task():
51
+ data = request.get_json()
52
+ if not data or "task_id" not in data:
53
+ return jsonify({"error": "يجب تحديد task_id"}), 400
54
+
55
+ peer = select_best_peer()
56
+ if not peer:
57
+ return jsonify({"error": "لا توجد أجهزة متاحة حالياً"}), 503
58
+
59
+ try:
60
+ resp = requests.post(peer, json=data, timeout=10)
61
+ if resp.ok:
62
+ return jsonify({"status": "success", "result": resp.json()})
63
+ else:
64
+ return jsonify({"error": "فشل إرسال المهمة"}), 500
65
+ except Exception as e:
66
+ logging.error(f"❌ خطأ في إرسال المهمة: {e}")
67
+ return jsonify({"error": str(e)}), 500
68
+
69
+ # ─────────────── API تحديث حالة الأجهزة ───────────────
70
+ @app.route("/update_status", methods=["POST"])
71
+ def update_status():
72
+ data = request.json
73
+ node_id = data.get("node_id")
74
+ if not node_id:
75
+ return jsonify({"error": "node_id مطلوب"}), 400
76
+
77
+ connected_peers[node_id] = {
78
+ "cpu": data.get("cpu"),
79
+ "ram": data.get("ram"),
80
+ "gpu": data.get("gpu")
81
+ }
82
+ socketio.emit("update_peers", connected_peers, broadcast=True)
83
+ return jsonify({"status": "ok"})
84
+
85
+ # ─────────────── صفحة Dashboard ───────────────
86
+ @app.route("/")
87
+ def index():
88
+ return render_template("dashboard.html")
89
+
90
+ # ─────────────── دردشة ───────────────
91
+ @socketio.on("send_message")
92
+ def handle_message(data):
93
+ socketio.emit("receive_message", data, broadcast=True)
94
+
95
+ # ─────────────── تشغيل السيرفر ───────────────
96
+ if __name__ == "__main__":
97
+ logging.info("🚀 بدء السيرفر المركزي مع Dashboard ودردشة")
98
+ socketio.run(app, host="0.0.0.0", port =5005)
global_memory.json CHANGED
The diff for this file is too large to render. See raw diff
 
gui.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import toga
2
+ from toga.style import Pack
3
+ from toga.style.pack import COLUMN, CENTER
4
+
5
+ class CoreFlowGUI(toga.App):
6
+ def startup(self):
7
+ label = toga.Label("مرحبًا بك في CoreFlow!", style=Pack(text_align=CENTER, font_size=18))
8
+ button = toga.Button("اضغطني", on_press=self.say_hello, style=Pack(padding=10))
9
+
10
+ box = toga.Box(style=Pack(direction=COLUMN, alignment=CENTER, padding=20))
11
+ box.add(label)
12
+ box.add(button)
13
+
14
+ self.main_window = toga.MainWindow(title=self.formal_name)
15
+ self.main_window.content = box
16
+ self.main_window.show()
17
+
18
+ def say_hello(self, widget):
19
+ self.main_window.info_dialog("تحية", "أهلاً بك يا أسامة 👋")
20
+
21
+ def main():
22
+ return CoreFlowGUI()
internet_scanner.py CHANGED
@@ -8,6 +8,7 @@ import time
8
  import socket
9
  from concurrent.futures import ThreadPoolExecutor, as_completed
10
  import logging
 
11
 
12
  class InternetScanner:
13
  def __init__(self):
@@ -19,7 +20,7 @@ class InternetScanner:
19
  "208.67.222.0/24", # OpenDNS range
20
  ]
21
 
22
- def scan_ip_range(self, ip_range: str, port: int = 7520):
23
  """مسح نطاق IP للبحث عن خوادم DTS"""
24
  import ipaddress
25
 
@@ -48,7 +49,7 @@ class InternetScanner:
48
  logging.error(f"خطأ في مسح النطاق {ip_range}: {e}")
49
  return []
50
 
51
- def check_dts_node(self, ip: str, port: int = 7520) -> str:
52
  """فحص IP معين للتأكد من وجود خادم DTS مع المشروع"""
53
  try:
54
  # فحص صفحة الصحة العامة
@@ -94,7 +95,7 @@ class InternetScanner:
94
  # البحث في GitHub عن مشاريع DTS
95
  github_api = "https://api.github.com/search/repositories"
96
  params = {
97
- "q": "distributed task system port:7520",
98
  "sort": "updated",
99
  "per_page": 10
100
  }
@@ -122,7 +123,7 @@ class InternetScanner:
122
  try:
123
  # التحقق من صحة IP
124
  socket.inet_aton(ip)
125
- peer_url = f"http://{ip}:7520/run"
126
 
127
  # فحص سريع
128
  if self.check_dts_node(ip):
 
8
  import socket
9
  from concurrent.futures import ThreadPoolExecutor, as_completed
10
  import logging
11
+ from peer_discovery import PORT
12
 
13
  class InternetScanner:
14
  def __init__(self):
 
20
  "208.67.222.0/24", # OpenDNS range
21
  ]
22
 
23
+ def scan_ip_range(self, ip_range: str, port: int = PORT):
24
  """مسح نطاق IP للبحث عن خوادم DTS"""
25
  import ipaddress
26
 
 
49
  logging.error(f"خطأ في مسح النطاق {ip_range}: {e}")
50
  return []
51
 
52
+ def check_dts_node(self, ip: str, port: int = PORT) -> str:
53
  """فحص IP معين للتأكد من وجود خادم DTS مع المشروع"""
54
  try:
55
  # فحص صفحة الصحة العامة
 
95
  # البحث في GitHub عن مشاريع DTS
96
  github_api = "https://api.github.com/search/repositories"
97
  params = {
98
+ "q": "distributed task system port:PORT",
99
  "sort": "updated",
100
  "per_page": 10
101
  }
 
123
  try:
124
  # التحقق من صحة IP
125
  socket.inet_aton(ip)
126
+ peer_url = f"http://{ip}:PORT/run"
127
 
128
  # فحص سريع
129
  if self.check_dts_node(ip):
launcher.py CHANGED
@@ -11,6 +11,7 @@ import subprocess
11
  import argparse
12
  import time
13
  from pathlib import Path
 
14
 
15
  def check_requirements():
16
  """فحص المتطلبات والاعتماديات"""
 
11
  import argparse
12
  import time
13
  from pathlib import Path
14
+ from peer_discovery import PORT
15
 
16
  def check_requirements():
17
  """فحص المتطلبات والاعتماديات"""
live_streaming.py CHANGED
@@ -13,6 +13,7 @@ from datetime import datetime
13
  from processor_manager import should_offload
14
  from remote_executor import execute_remotely
15
  from functools import wraps
 
16
 
17
  logging.basicConfig(level=logging.INFO)
18
 
 
13
  from processor_manager import should_offload
14
  from remote_executor import execute_remotely
15
  from functools import wraps
16
+ from peer_discovery import PORT
17
 
18
  logging.basicConfig(level=logging.INFO)
19
 
load_balancer.py CHANGED
@@ -1,5 +1,6 @@
1
  # load_balancer.py
2
  import peer_discovery, requests, time, smart_tasks, psutil, socket
 
3
 
4
  def send(peer, func, *args, **kw):
5
  try:
 
1
  # load_balancer.py
2
  import peer_discovery, requests, time, smart_tasks, psutil, socket
3
+ from peer_discovery import PORT
4
 
5
  def send(peer, func, *args, **kw):
6
  try:
node_client.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # ================================================================
3
+ # node_client.py – عميل تسجيل العُقدة في نظام AmalOffload
4
+ # ---------------------------------------------------------------
5
+ # • يختار منفذًا (من ENV أو من مجموعة PORTS).
6
+ # • يجلب عنوان الـ IP المحلي.
7
+ # • يحاول التسجيل في خادم سجلٍّ مركزي واحد تِلو الآخر،
8
+ # وعلى كل المنافذ، حتى ينجح.
9
+ # • عند النجاح يُرجع قائمة الأقران (Peers) من الخادم.
10
+ # ================================================================
11
+
12
+ import os
13
+ import socket
14
+ import time
15
+ import logging
16
+ import random
17
+ import requests
18
+ from typing import Iterable, Tuple, List
19
+
20
+ # ⬇️ منافذ مقترحة؛ يمكنك التعديل أو توليدها ديناميكيًا
21
+ DEFAULT_PORTS = {
22
+ 7520, 7384, 9021, 6998, 5810, 9274,
23
+ 8645, 7329, 7734, 8456, 6173, 7860,
24
+ }
25
+
26
+ # ⬇️ خوادم السجل الاحتياطية بالترتيب المفضَّل
27
+ DEFAULT_REGISTRY_SERVERS = [
28
+ "https://cv4790811.regru.cloud",
29
+ "https://amaloffload.onrender.com",
30
+ "https://osamabyc86-offload.hf.space",
31
+ "http://10.229.36.125",
32
+ "http://10.229.228.178",
33
+ ]
34
+
35
+ logging.basicConfig(
36
+ level=logging.INFO,
37
+ format="%(asctime)s [%(levelname)s] %(message)s",
38
+ datefmt="%H:%M:%S",
39
+ )
40
+
41
+
42
+ class NodeClient:
43
+ """
44
+ عميل خفيف يعتني بالتسجيل المتكرِّر في خادم سجل مركزي.
45
+ يمكن استيراده في أي سكربت وتشغيله في خيط منفصل.
46
+ """
47
+
48
+ def __init__(
49
+ self,
50
+ PORTs: Iterable[int] | None = None,
51
+ registry_servers: List[str] | None = None,
52
+ node_id: str | None = None,
53
+ ):
54
+ self.PORTs = set(PORTs) if PORTs else DEFAULT_PORTS
55
+ self.registry_servers = list(registry_servers) if registry_servers else DEFAULT_REGISTRY_SERVERS
56
+ self.node_id = node_id or os.getenv("NODE_ID", socket.gethostname())
57
+
58
+ # مبدئيًّا اختَر منفذًا (أولوية للمتغيّر البيئي إن وُجد)
59
+ self.port: int = int(os.getenv("CPU_PORT", random.choice(list(self.PORTs))))
60
+ self.current_server_index: int | None = None
61
+
62
+ # -------------------------------------------------------------------------
63
+ @staticmethod
64
+ def get_local_ip() -> str:
65
+ """يحاول معرفة أفضل عنوان IP محلي لاستخدامه في الشبكة."""
66
+ try:
67
+ with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
68
+ # لا يهم أن ينجح الاتصال الفعلي، الهدف كشف IP واجهة الخروج
69
+ s.connect(("10.255.255.255", 1))
70
+ return s.getsockname()[0]
71
+ except Exception:
72
+ return "127.0.0.1"
73
+
74
+ def _register_once(self, server: str, port: int) -> List[str]:
75
+ """مُحاولة واحدة للتسجيل؛ تُعيد peers أو ترفع استثناءً."""
76
+ payload = {
77
+ "node_id": self.node_id,
78
+ "ip": self.get_local_ip(),
79
+ "port": port,
80
+ }
81
+ resp = requests.post(f"{server}/register", json=payload, timeout=5)
82
+ resp.raise_for_status()
83
+ return resp.json() # توقّع أن الخادم يُرجع قائمة أقران
84
+
85
+ # -------------------------------------------------------------------------
86
+ def connect_until_success(self, retry_delay: int = 5) -> Tuple[str, List[str]]:
87
+ """
88
+ يدور على جميع المنافذ والخوادم حتى ينجح التسجيل.
89
+ • عند النجاح يُرجع: (عنوان الخادم، قائمة الأقران)
90
+ • لا يرفع استثناءات؛ إمّا ينجح أو يستمر في المحاولة إلى ما لا نهاية.
91
+ """
92
+ logging.info("🔄 بدء محاولات التسجيل للعقدة '%s'...", self.node_id)
93
+ while True:
94
+ for port in self.PORTs:
95
+ for idx, server in enumerate(self.registry_servers):
96
+ try:
97
+ peers = self._register_once(server, port)
98
+ # سجّل النجاح واحفظ المعلومات
99
+ self.port = port
100
+ self.current_server_index = idx
101
+ logging.info("✅ متصل: %s على المنفذ %s", server, port)
102
+ return server, peers
103
+ except Exception as e:
104
+ logging.debug("❌ %s:%s -> %s", server, port, e)
105
+ time.sleep(retry_delay) # انتظر قليلًا ثم أعد المحاولة
106
+
107
+ # -------------------------------------------------------------------------
108
+ def run_background(self) -> None:
109
+ """
110
+ إطلاق التسجيل في خيط منفصل؛ مفيد إذا كنت تريد
111
+ إبقاء Main Thread للمهام الأخرى.
112
+ """
113
+ import threading # استيراد متأخر لتفادي الحمل الزائد عند import
114
+ threading.Thread(target=self.connect_until_success, daemon=True).start()
115
+
116
+
117
+ # -----------------------------------------------------------------------------
118
+ if __name__ == "__main__":
119
+ """
120
+ للتجربة المباشرة:
121
+ $ python node_client.py
122
+ """
123
+ client = NodeClient()
124
+ server, peer_list = client.connect_until_success()
125
+ logging.info("🗂️ الأقران: %s", peer_list)
package-lock.json CHANGED
The diff for this file is too large to render. See raw diff
 
package.json CHANGED
@@ -42,9 +42,7 @@
42
  "@radix-ui/react-toggle-group": "^1.1.3",
43
  "@radix-ui/react-tooltip": "^1.2.0",
44
  "@tanstack/react-query": "^5.60.5",
45
- "@types/bcryptjs": "^2.4.6",
46
- "@types/jsonwebtoken": "^9.0.9",
47
- "bcryptjs": "^3.0.2",
48
  "class-variance-authority": "^0.7.1",
49
  "clsx": "^2.1.1",
50
  "cmdk": "^1.1.1",
@@ -56,21 +54,17 @@
56
  "express": "^4.21.2",
57
  "express-session": "^1.18.1",
58
  "framer-motion": "^11.13.1",
59
- "i18next": "^25.2.0",
60
  "input-otp": "^1.4.2",
61
- "jsonwebtoken": "^9.0.2",
62
  "lucide-react": "^0.453.0",
63
  "memorystore": "^1.6.7",
 
64
  "next-themes": "^0.4.6",
65
- "node-cron": "^4.0.5",
66
- "nodemailer": "^7.0.3",
67
  "passport": "^0.7.0",
68
  "passport-local": "^1.0.0",
69
  "react": "^18.3.1",
70
  "react-day-picker": "^8.10.1",
71
  "react-dom": "^18.3.1",
72
  "react-hook-form": "^7.55.0",
73
- "react-i18next": "^15.5.1",
74
  "react-icons": "^5.4.0",
75
  "react-resizable-panels": "^2.1.7",
76
  "recharts": "^2.15.2",
@@ -84,7 +78,7 @@
84
  "zod-validation-error": "^3.4.0"
85
  },
86
  "devDependencies": {
87
- "@replit/vite-plugin-cartographer": "^0.2.0",
88
  "@replit/vite-plugin-runtime-error-modal": "^0.0.3",
89
  "@tailwindcss/typography": "^0.5.15",
90
  "@tailwindcss/vite": "^4.1.3",
@@ -100,12 +94,14 @@
100
  "@vitejs/plugin-react": "^4.3.2",
101
  "autoprefixer": "^10.4.20",
102
  "drizzle-kit": "^0.30.4",
 
 
103
  "esbuild": "^0.25.0",
104
  "postcss": "^8.4.47",
105
  "tailwindcss": "^3.4.17",
106
  "tsx": "^4.19.1",
107
  "typescript": "5.6.3",
108
- "vite": "^5.4.14"
109
  },
110
  "optionalDependencies": {
111
  "bufferutil": "^4.0.8"
 
42
  "@radix-ui/react-toggle-group": "^1.1.3",
43
  "@radix-ui/react-tooltip": "^1.2.0",
44
  "@tanstack/react-query": "^5.60.5",
45
+ "bonjour-service": "^1.3.0",
 
 
46
  "class-variance-authority": "^0.7.1",
47
  "clsx": "^2.1.1",
48
  "cmdk": "^1.1.1",
 
54
  "express": "^4.21.2",
55
  "express-session": "^1.18.1",
56
  "framer-motion": "^11.13.1",
 
57
  "input-otp": "^1.4.2",
 
58
  "lucide-react": "^0.453.0",
59
  "memorystore": "^1.6.7",
60
+ "nanoid": "^5.1.5",
61
  "next-themes": "^0.4.6",
 
 
62
  "passport": "^0.7.0",
63
  "passport-local": "^1.0.0",
64
  "react": "^18.3.1",
65
  "react-day-picker": "^8.10.1",
66
  "react-dom": "^18.3.1",
67
  "react-hook-form": "^7.55.0",
 
68
  "react-icons": "^5.4.0",
69
  "react-resizable-panels": "^2.1.7",
70
  "recharts": "^2.15.2",
 
78
  "zod-validation-error": "^3.4.0"
79
  },
80
  "devDependencies": {
81
+ "@replit/vite-plugin-cartographer": "^0.2.7",
82
  "@replit/vite-plugin-runtime-error-modal": "^0.0.3",
83
  "@tailwindcss/typography": "^0.5.15",
84
  "@tailwindcss/vite": "^4.1.3",
 
94
  "@vitejs/plugin-react": "^4.3.2",
95
  "autoprefixer": "^10.4.20",
96
  "drizzle-kit": "^0.30.4",
97
+ "electron": "^37.1.0",
98
+ "electron-builder": "^26.0.12",
99
  "esbuild": "^0.25.0",
100
  "postcss": "^8.4.47",
101
  "tailwindcss": "^3.4.17",
102
  "tsx": "^4.19.1",
103
  "typescript": "5.6.3",
104
+ "vite": "^5.4.19"
105
  },
106
  "optionalDependencies": {
107
  "bufferutil": "^4.0.8"
peer_discovery.py CHANGED
@@ -4,137 +4,95 @@ import socket
4
  import threading
5
  import time
6
  import logging
7
-
8
  import requests
9
  from zeroconf import Zeroconf, ServiceInfo, ServiceBrowser
10
 
11
- # 👇 إعداد الـ peer discovery عبر LAN وInternet
12
- SERVICE = "_tasknode._tcp.local."
13
- PORT = int(os.getenv("CPU_PORT", "7520"))
14
- PEERS = set() # مجموعة URLs للأقران (/run)
15
 
16
- # 🌐 خادم وسيط مركزي (Central Registry)
17
- CENTRAL_REGISTRY_URL = "https://cv4790811.regru.cloud"
18
 
19
- # 🟢 دالة لحساب IP العام أو المحلي
20
- # تستخدم HTTP API للحصول على IP عام ثم fallback إلى LAN
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  def get_local_ip():
23
- # حاول الحصول على IP عام
24
  try:
25
- r = requests.get("https://api.ipify.org?format=json", timeout=3)
26
- r.raise_for_status()
27
- data = r.json()
28
- return data.get("ip", "127.0.0.1")
 
29
  except Exception:
30
- # fallback إلى LAN IP
31
- try:
32
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
33
- s.connect(("8.8.8.8", 80))
34
- return s.getsockname()[0]
35
- except Exception:
36
- return "127.0.0.1"
37
- finally:
38
- try:
39
- s.close()
40
- except Exception:
41
- pass
42
 
43
- # تسجيل الخدمة في شبكة LAN عبر Zeroconf
44
- # للحفاظ على قدرة اكتشاف peers في نفس الشبكة المحلية
45
- def register_service_lan():
46
- zc = Zeroconf()
47
- local_ip = get_local_ip()
48
- info = ServiceInfo(
49
- SERVICE,
50
- f"{socket.gethostname()}.{SERVICE}",
51
- addresses=[socket.inet_aton(local_ip)],
52
- port=PORT,
53
- properties={b'load': b'0'}
54
- )
55
- try:
56
- zc.register_service(info)
57
- print(f"✅ LAN service registered: {local_ip}:{PORT}")
58
- except Exception as e:
59
- print(f"❌ LAN registration failed: {e}")
60
-
61
- # ❷ مستمع لاكتشاف أجهزة LAN عبر Zeroconf
62
- class Listener:
63
- def add_service(self, zc, t, name):
64
- info = zc.get_service_info(t, name)
65
- if info and info.addresses:
66
- ip = socket.inet_ntoa(info.addresses[0])
67
- peer_url = f"http://{ip}:{info.port}/run"
68
- if peer_url not in PEERS:
69
- PEERS.add(peer_url)
70
- print(f"🔗 LAN peer discovered: {peer_url}")
71
- def update_service(self, zc, t, name):
72
- self.add_service(zc, t, name)
73
- def remove_service(self, zc, t, name):
74
- print(f"❌ LAN peer removed: {name}")
75
-
76
- # حلقة اكتشاف LAN مستمرة
77
- def discover_lan_loop():
78
- zc = Zeroconf()
79
- ServiceBrowser(zc, SERVICE, Listener())
80
- print(f"🔍 Started LAN discovery for {SERVICE}")
81
- while True:
82
- time.sleep(5)
83
 
84
- # ❸ تسجيل العقدة في الخادم المركزي
85
- # ترسل بياناتها إلى /register وتضيف باقي الأقران
86
- def register_with_central():
87
- node_id = os.getenv("NODE_ID", socket.gethostname())
88
- info = {"node_id": node_id, "ip": get_local_ip(), "port": PORT}
89
- try:
90
- resp = requests.post(f"{CENTRAL_REGISTRY_URL}/register", json=info, timeout=5)
91
- resp.raise_for_status()
92
- peers_list = resp.json()
93
- for p in peers_list:
94
- peer_url = f"http://{p['ip']}:{p['port']}/run"
95
- if peer_url not in PEERS:
96
- PEERS.add(peer_url)
97
- print(f"🌐 Registered and discovered central peer: {peer_url}")
98
- except Exception as e:
99
- print(f"❌ Central registration failed: {e}")
100
 
101
- # مزامنة ال��قران من الخادم المركزي بشكل دوري
102
- # تُحدّث مجموعة PEERS كل 5 دقائق عن طريق /peers endpoint
103
- def fetch_central_loop():
104
- print("🔄 Central registry sync loop started")
105
- while True:
106
- try:
107
- resp = requests.get(f"{CENTRAL_REGISTRY_URL}/peers", timeout=5)
108
- resp.raise_for_status()
109
- peers_list = resp.json()
110
- for p in peers_list:
111
- peer_url = f"http://{p['ip']}:{p['port']}/run"
112
- if peer_url not in PEERS:
113
- PEERS.add(peer_url)
114
- print(f"🌐 Central peer discovered: {peer_url}")
115
- except Exception as e:
116
- print(f"⚠️ Fetch central peers failed: {e}")
117
- time.sleep(300)
118
 
119
- # 🚀 دالة الإدخال الرئيسيّة
120
  def main():
121
- logging.basicConfig(level=logging.INFO)
122
- print("🚀 Peer Discovery System starting...")
123
 
124
- # Zeroconf LAN registration & discovery
125
- threading.Thread(target=register_service_lan, daemon=True).start()
126
- threading.Thread(target=discover_lan_loop, daemon=True).start()
 
 
 
 
 
 
 
 
127
 
128
- # التسجيل في الخادم الوسيط ومزامنة الأقران
129
- register_with_central()
130
- threading.Thread(target=fetch_central_loop, daemon=True).start()
131
 
132
- # إبقاء السكربت قيد التشغيل
133
  try:
134
  while True:
135
- time.sleep(60)
 
136
  except KeyboardInterrupt:
137
- print("🛑 Exiting...")
 
 
 
138
 
139
  if __name__ == "__main__":
140
  main()
 
4
  import threading
5
  import time
6
  import logging
 
7
  import requests
8
  from zeroconf import Zeroconf, ServiceInfo, ServiceBrowser
9
 
10
+ # إعداد السجلات
11
+ logging.basicConfig(level=logging.INFO)
12
+ logger = logging.getLogger(__name__)
 
13
 
14
+ # منفذ الخدمة (بدءاً من 1000 مع زيادة متسلسلة)
15
+ current_port = 1000
16
 
17
+ def get_sequential_port():
18
+ global current_port
19
+ port = current_port
20
+ current_port += 1
21
+ if current_port > 9999:
22
+ current_port = 1000
23
+ return port
24
+
25
+ PORT = "7520" and int(os.getenv("CPU_PORT", get_sequential_port()))
26
+ SERVICE = "_tasknode._tcp.local."
27
+ PEERS = set()
28
+ PEERS_INFO = {}
29
+
30
+ CENTRAL_REGISTRY_SERVERS = [
31
+ "https://cv4790811.regru.cloud",
32
+ "https://amaloffload.onrender.com",
33
+ "https://osamabyc86-offload.hf.space",
34
+ "https://osamabyc19866-omsd.hf.space",
35
+ "https://52.13.128.108",
36
+ "https://176.28.175.216",
37
+ "https://44.229.227.142",
38
+ "https://osamabyc86-amalcoreflow.hf.space"
39
+ ]
40
 
41
  def get_local_ip():
 
42
  try:
43
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
44
+ s.connect(("8.8.8.8", 80))
45
+ ip = s.getsockname()[0]
46
+ s.close()
47
+ return ip
48
  except Exception:
49
+ return "127.0.0.1"
 
 
 
 
 
 
 
 
 
 
 
50
 
51
+ def register_peer(ip, port):
52
+ peer_url = f"http://{ip}:{port}/run"
53
+ if peer_url not in PEERS:
54
+ PEERS.add(peer_url)
55
+ logger.info(f"تم تسجيل قرين جديد: {peer_url}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
+ def discover_lan_peers():
58
+ class Listener:
59
+ def add_service(self, zc, type_, name):
60
+ info = zc.get_service_info(type_, name)
61
+ if info:
62
+ ip = socket.inet_ntoa(info.addresses[0])
63
+ register_peer(ip, info.port)
 
 
 
 
 
 
 
 
 
64
 
65
+ zeroconf = Zeroconf()
66
+ ServiceBrowser(zeroconf, SERVICE, Listener())
67
+ return zeroconf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
 
69
  def main():
70
+ logger.info("🚀 بدء نظام اكتشاف الأقران...")
 
71
 
72
+ # تسجيل الخدمة المحلية
73
+ zeroconf = Zeroconf()
74
+ info = ServiceInfo(
75
+ type_=SERVICE,
76
+ name=f"{socket.gethostname()}.{SERVICE}",
77
+ addresses=[socket.inet_aton(get_local_ip())],
78
+ port=int(PORT),
79
+ properties={b'version': b'1.0'},
80
+ server=f"{socket.gethostname()}.local."
81
+ )
82
+ zeroconf.register_service(info)
83
 
84
+ # بدء اكتشاف الأقران
85
+ discover_lan_peers()
 
86
 
 
87
  try:
88
  while True:
89
+ logger.info(f"عدد الأقران المكتشفين: {len(PEERS)}")
90
+ time.sleep(10)
91
  except KeyboardInterrupt:
92
+ logger.info("🛑 إيقاف النظام...")
93
+ finally:
94
+ zeroconf.unregister_service(info)
95
+ zeroconf.close()
96
 
97
  if __name__ == "__main__":
98
  main()
peer_registry.py CHANGED
@@ -1,6 +1,7 @@
1
  import socket
2
  import time
3
  from zeroconf import Zeroconf, ServiceBrowser, ServiceInfo
 
4
 
5
  class Listener:
6
  def __init__(self):
@@ -55,7 +56,7 @@ def discover_peers(timeout=2):
55
 
56
  if __name__ == "__main__":
57
  local_ip = socket.gethostbyname(socket.gethostname())
58
- port = 7520
59
 
60
  zc = register_service(local_ip, port, load=0.1)
61
 
 
1
  import socket
2
  import time
3
  from zeroconf import Zeroconf, ServiceBrowser, ServiceInfo
4
+ from peer_discovery import PORT
5
 
6
  class Listener:
7
  def __init__(self):
 
56
 
57
  if __name__ == "__main__":
58
  local_ip = socket.gethostbyname(socket.gethostname())
59
+ port = PORT
60
 
61
  zc = register_service(local_ip, port, load=0.1)
62
 
peer_server.py CHANGED
@@ -5,8 +5,20 @@ import psutil
5
  import smart_tasks
6
  import time
7
  import socket
8
- import peer_discovery # إذا كان يستخدم لاحقًا
9
-
 
 
 
 
 
 
 
 
 
 
 
 
10
  app = Flask(__name__) # إنشاء التطبيق
11
 
12
  @app.route("/cpu")
@@ -33,5 +45,5 @@ def run():
33
  return jsonify(error=str(e)), 500
34
 
35
  if __name__ == "__main__": # التصحيح هنا
36
- app.run(host="0.0.0.0", port=7520)
37
 
 
5
  import smart_tasks
6
  import time
7
  import socket
8
+ from peer_discovery import PORT
9
+ from flask import Flask
10
+ app = Flask(__name__)
11
+ @app.route("/run", methods=["POST"])
12
+ def run_task():
13
+ try:
14
+ data = request.get_json()
15
+ print("🔹 البيانات المستلمة:", data)
16
+ count = data.get("count", 100)
17
+ ...
18
+ return jsonify(result)
19
+ except Exception as e:
20
+ print("❌ خطأ أثناء التنفيذ:", e)
21
+ return jsonify({"error": str(e)}), 500
22
  app = Flask(__name__) # إنشاء التطبيق
23
 
24
  @app.route("/cpu")
 
45
  return jsonify(error=str(e)), 500
46
 
47
  if __name__ == "__main__": # التصحيح هنا
48
+ app.run(host="0.0.0.0", port=PORT)
49
 
quick_connection_test.py CHANGED
@@ -13,7 +13,7 @@ def test_connection():
13
 
14
  # 1. فحص الخادم المحلي
15
  try:
16
- response = requests.get("http://localhost:7520/health", timeout=3)
17
  if response.status_code == 200:
18
  print("✅ الخادم المحلي يعمل")
19
  else:
 
13
 
14
  # 1. فحص الخادم المحلي
15
  try:
16
+ response = requests.get("http://localhost:PORT/health", timeout=3)
17
  if response.status_code == 200:
18
  print("✅ الخادم المحلي يعمل")
19
  else:
ram_manager.py ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ram_manager.py – Distributed RAM Offload Agent
3
+ ================================================
4
+
5
+ ❖ الغرض
6
+ ------------
7
+ يوفِّر هذا الملف إضافة مستقلة إلى مشروع **AmalOffload** من أجل مشاركة الذاكرة (RAM) بين جميع العُقد التي تشغِّل المشروع. عندما ينخفض مقدار الذاكرة الحرة على إحدى العُقد إلى أقل من 2 جيجابايت (أو أي قيمة تحدّدها)، تُنقل كتل بيانات إلى عُقد أخرى ما تزال تملك ذاكرة حرّة.
8
+
9
+ ❖ المزايا الرئيسة
10
+ ------------------
11
+ * يراقب استهلاك الذاكرة محليًّا بانتظام.
12
+ * يعلن عن نفسه ويكتشف الأقران (Peers) تلقائيًّا بالاعتماد على `peer_registry` إن وُجد، أو على قائمة في المتغيّر البيئي `CENTRAL_PEERS` كحلّ احتياطي.
13
+ * يعرض واجهة HTTP بسيطة (`Flask`) بثلاث مسارات:
14
+ * `GET /ram_status` → يُرجِع مقدار الذاكرة الحرّة بالعُقدة.
15
+ * `POST /ram_store` → يستقبل كتلة بيانات (Base64) ويحجزها في الذاكرة.
16
+ * `GET /ram_fetch/<id>` → يُرجِع كتلة بيانات مُخزّنة بحسب معرّفها.
17
+
18
+ ❖ طريقة التشغيل
19
+ ----------------
20
+ ```bash
21
+ python ram_manager.py --ram-limit 2048 --chunk 64 --interval 5
22
+ ```
23
+ أو اكتفِ بالتشغيل بدون وسائط واعتمد على القيم الافتراضيّة أو على متغيّرات البيئة:
24
+ ```bash
25
+ export RAM_THRESHOLD_MB=2048
26
+ export RAM_CHUNK_MB=64
27
+ python ram_manager.py
28
+ ```
29
+
30
+ ❖ التعليمات البرمجيّة
31
+ ----------------------
32
+ """
33
+ import os
34
+ import psutil
35
+ import time
36
+ import threading
37
+ import socket
38
+ import base64
39
+ import uuid
40
+ from typing import Dict, List
41
+
42
+ try:
43
+ from flask import Flask, request, jsonify
44
+ except ImportError as exc:
45
+ raise RuntimeError("Flask غير مُثبّت. نفِّذ: pip install flask") from exc
46
+
47
+ # محاولة استيراد مُسجِّل الأقران الحالي من المشروع
48
+ try:
49
+ import peer_registry # يتوقع أن يحتوي على list_peers()
50
+ except ImportError:
51
+ peer_registry = None
52
+
53
+ # الإعدادات – قابلة للتعديل عبر متغيّرات البيئة
54
+ RAM_LIMIT_MB = int(os.getenv("RAM_THRESHOLD_MB", "2048")) # الحد الأدنى للرام الحرّة قبل الت offload
55
+ CHUNK_MB = int(os.getenv("RAM_CHUNK_MB", "64")) # حجم الكتلة المُرسَلة
56
+ CHECK_INTERVAL = int(os.getenv("RAM_CHECK_INTERVAL", "5")) # ثواني بين كل فحص
57
+ RAM_PORT = int(os.getenv("RAM_PORT", "8765")) # بورت واجهة الذاكرة
58
+
59
+ app = Flask(__name__)
60
+
61
+ # مخزن الكتل الواردة
62
+ remote_chunks: Dict[str, bytes] = {}
63
+
64
+ def get_free_ram_mb() -> int:
65
+ """الذاكرة الحرّة بالميغابايت"""
66
+ return psutil.virtual_memory().available // (1024 * 1024)
67
+
68
+ # ─────────────────── واجهة HTTP ────────────────────
69
+ @app.route("/ram_status", methods=["GET"])
70
+ def ram_status():
71
+ """إرجاع كميّة الذاكرة الحرّة بالعُقدة."""
72
+ return jsonify({"free_mb": get_free_ram_mb()})
73
+
74
+ @app.route("/ram_store", methods=["POST"])
75
+ def ram_store():
76
+ """تلقّي كتلة بيانات وتخزينها."""
77
+ payload = request.get_json(force=True)
78
+ cid = payload["id"]
79
+ blob_b64= payload["data"]
80
+ remote_chunks[cid] = base64.b64decode(blob_b64)
81
+ return jsonify({"status": "stored", "id": cid})
82
+
83
+ @app.route("/ram_fetch/<cid>", methods=["GET"])
84
+ def ram_fetch(cid):
85
+ blob = remote_chunks.get(cid)
86
+ if blob is None:
87
+ return jsonify({"error": "not found"}), 404
88
+ return jsonify({"id": cid, "data": base64.b64encode(blob).decode()})
89
+
90
+ # ─────────────────── وظائف داخليّة ───────────────────
91
+
92
+ def start_api():
93
+ """تشغيل خادم Flask في خيط منفصل."""
94
+ from werkzeug.serving import make_server
95
+ server = make_server("0.0.0.0", RAM_PORT, app)
96
+ server.serve_forever()
97
+
98
+
99
+ def discover_peers() -> List[str]:
100
+ """الحصول على قائمة IPs للأقران، باستثناء عنوان الجهاز الحالي."""
101
+ peers: List[str] = []
102
+
103
+ if peer_registry and hasattr(peer_registry, "list_peers"):
104
+ try:
105
+ peers_info = peer_registry.list_peers() # متوقع: [{"ip": "..."}, ...]
106
+ peers = [p["ip"] for p in peers_info if p.get("ip")]
107
+ except Exception:
108
+ pass
109
+ else:
110
+ central_env = os.getenv("CENTRAL_PEERS", "")
111
+ if central_env:
112
+ peers = central_env.split(",")
113
+
114
+ # إزالة عنوان الجهاز المحلي
115
+ try:
116
+ local_ip = socket.gethostbyname(socket.gethostname())
117
+ peers = [ip for ip in peers if ip != local_ip]
118
+ except Exception:
119
+ pass
120
+
121
+ return peers
122
+
123
+
124
+ def offload_chunk(blob: bytes, peer_ip: str) -> bool:
125
+ """إرسال كتلة بيانات إلى peer محدّد."""
126
+ import requests
127
+ try:
128
+ resp = requests.post(
129
+ f"http://{peer_ip}:{RAM_PORT}/ram_store",
130
+ json={"id": str(uuid.uuid4()), "data": base64.b64encode(blob).decode()},
131
+ timeout=5,
132
+ )
133
+ return resp.status_code == 200
134
+ except Exception:
135
+ return False
136
+
137
+
138
+ def monitor_loop():
139
+ """مراقبة الذاكرة واستدعاء offload عند الحاجة."""
140
+ while True:
141
+ free_mb = get_free_ram_mb()
142
+ if free_mb < RAM_LIMIT_MB:
143
+ peers = discover_peers()
144
+ if not peers:
145
+ print("[RAM] لا يوجد أقران متاحون حاليًا.")
146
+ else:
147
+ blob = bytes(CHUNK_MB * 1024 * 1024) # كتلة وهميّة – استبدلها ببيانات حقيقيّة عند الدمج
148
+ for ip in peers:
149
+ if offload_chunk(blob, ip):
150
+ print(f"[RAM]‎ أرسلت ‎{CHUNK_MB}‎MB إلى ‎{ip}")
151
+ break
152
+ else:
153
+ print("[RAM] كل الأقران رفضوا التخزين أو حدث خطأ.")
154
+ time.sleep(CHECK_INTERVAL)
155
+
156
+
157
+ def main():
158
+ threading.Thread(target=start_api, daemon=True).start()
159
+ monitor_loop()
160
+
161
+ if __name__ == "__main__":
162
+ main()
remote_executor.py CHANGED
@@ -12,11 +12,12 @@ from typing import Any
12
 
13
  # قائمة الأقران (URLs) المستخرجة من peer_discovery
14
  from peer_discovery import PEERS
 
15
 
16
  # عنوان افتراضي احتياطي (يمكن تغييره بمتغير بيئي REMOTE_SERVER)
17
  FALLBACK_SERVER = os.getenv(
18
  "REMOTE_SERVER",
19
- "http://89.111.171.92:7520/run"
20
  )
21
 
22
  # محاولة استيراد SecurityManager (اختياري)
 
12
 
13
  # قائمة الأقران (URLs) المستخرجة من peer_discovery
14
  from peer_discovery import PEERS
15
+ from peer_discovery import PORT
16
 
17
  # عنوان افتراضي احتياطي (يمكن تغييره بمتغير بيئي REMOTE_SERVER)
18
  FALLBACK_SERVER = os.getenv(
19
  "REMOTE_SERVER",
20
+ "http://89.111.171.92:PORT/run"
21
  )
22
 
23
  # محاولة استيراد SecurityManager (اختياري)
rpc_server.py CHANGED
@@ -9,6 +9,7 @@ from flask import Flask, request, jsonify
9
  import smart_tasks # «your_tasks» تمّ استيراده تحت هذا الاسم فى main.py
10
  import logging, json
11
  from security_layer import SecurityManager
 
12
 
13
  SECURITY = SecurityManager("my_shared_secret_123")
14
 
@@ -69,5 +70,5 @@ def run():
69
 
70
  # ------------------------------------------------------------------
71
  if name == "main":
72
- # تأكد أن المنفذ 7520 مفتوح
73
- app.run(host="0.0.0.0", port=7520)
 
9
  import smart_tasks # «your_tasks» تمّ استيراده تحت هذا الاسم فى main.py
10
  import logging, json
11
  from security_layer import SecurityManager
12
+ from peer_discovery import PORT
13
 
14
  SECURITY = SecurityManager("my_shared_secret_123")
15
 
 
70
 
71
  # ------------------------------------------------------------------
72
  if name == "main":
73
+ # تأكد أن المنفذ PORT مفتوح
74
+ app.run(host="0.0.0.0", port=PORT)
security_layer.py CHANGED
@@ -9,6 +9,7 @@ from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
9
  from cryptography.fernet import Fernet
10
  import os, base64, json
11
  from typing import Dict
 
12
 
13
 
14
  class SecurityManager:
 
9
  from cryptography.fernet import Fernet
10
  import os, base64, json
11
  from typing import Dict
12
+ from peer_discovery import PORT
13
 
14
 
15
  class SecurityManager:
server.py CHANGED
@@ -4,6 +4,7 @@ import json
4
  from your_tasks import *
5
  from project_identifier import create_project_endpoint, get_project_info
6
  import logging
 
7
 
8
  app = Flask(__name__)
9
  CORS(app)
@@ -21,7 +22,7 @@ def multiply():
21
 
22
  @app.route('/health', methods=['GET'])
23
  def health_check():
24
- return jsonify({"status": "healthy", "port": 7520})
25
 
26
  @app.route('/project_info', methods=['GET'])
27
  def project_info():
@@ -29,4 +30,4 @@ def project_info():
29
 
30
  if __name__ == "__main__":
31
  # هذا العنوان يسمح بالاستماع على IP خارجي لتلقي الاتصالات من الإنترنت
32
- app.run(host="0.0.0.0", port=7520)
 
4
  from your_tasks import *
5
  from project_identifier import create_project_endpoint, get_project_info
6
  import logging
7
+ from peer_discovery import PORT
8
 
9
  app = Flask(__name__)
10
  CORS(app)
 
22
 
23
  @app.route('/health', methods=['GET'])
24
  def health_check():
25
+ return jsonify({"status": "healthy", "port": PORT})
26
 
27
  @app.route('/project_info', methods=['GET'])
28
  def project_info():
 
30
 
31
  if __name__ == "__main__":
32
  # هذا العنوان يسمح بالاستماع على IP خارجي لتلقي الاتصالات من الإنترنت
33
+ app.run(host="0.0.0.0", port=PORT)
smart_tasks.py CHANGED
@@ -1,6 +1,7 @@
1
  import math
2
  import numpy as np
3
  import time
 
4
 
5
  def prime_calculation(n: int):
6
  """ترجع قائمة الأعداد الأوليّة حتى n مع عددها"""
@@ -135,4 +136,4 @@ def game_ai_processing(ai_agents_count, decision_complexity, game_state_size):
135
  "total_operations": total_operations,
136
  "processing_time": time.time() - start_time,
137
  "server_processed": True
138
- }
 
1
  import math
2
  import numpy as np
3
  import time
4
+ from peer_discovery import PORT
5
 
6
  def prime_calculation(n: int):
7
  """ترجع قائمة الأعداد الأوليّة حتى n مع عددها"""
 
136
  "total_operations": total_operations,
137
  "processing_time": time.time() - start_time,
138
  "server_processed": True
139
+ }
system_check.py CHANGED
@@ -7,6 +7,7 @@ import requests
7
  import psutil
8
  import threading
9
  from offload_lib import discover_peers
 
10
 
11
  def check_local_system():
12
  """فحص النظام المحلي"""
@@ -23,7 +24,7 @@ def check_server_running():
23
  """فحص إذا كان الخادم المحلي يعمل"""
24
  print("🌐 فحص الخادم المحلي...")
25
  try:
26
- response = requests.get("http://localhost:7520/health", timeout=3)
27
  if response.status_code == 200:
28
  print("✅ الخادم المحلي يعمل بشكل صحيح")
29
  return True
 
7
  import psutil
8
  import threading
9
  from offload_lib import discover_peers
10
+ from peer_discovery import PORT
11
 
12
  def check_local_system():
13
  """فحص النظام المحلي"""
 
24
  """فحص إذا كان الخادم المحلي يعمل"""
25
  print("🌐 فحص الخادم المحلي...")
26
  try:
27
+ response = requests.get("http://localhost:PORT/health", timeout=3)
28
  if response.status_code == 200:
29
  print("✅ الخادم المحلي يعمل بشكل صحيح")
30
  return True
system_tray.py CHANGED
@@ -9,6 +9,7 @@ import threading
9
  import requests
10
  import webbrowser
11
  from pathlib import Path
 
12
 
13
  try:
14
  import pystray
 
9
  import requests
10
  import webbrowser
11
  from pathlib import Path
12
+ from peer_discovery import PORT
13
 
14
  try:
15
  import pystray
task_splitter.py CHANGED
@@ -2,6 +2,7 @@
2
  from typing import Dict, Any, List
3
  import networkx as nx
4
  import hashlib
 
5
 
6
  class TaskSplitter:
7
  def __init__(self):
 
2
  from typing import Dict, Any, List
3
  import networkx as nx
4
  import hashlib
5
+ from peer_discovery import PORT
6
 
7
  class TaskSplitter:
8
  def __init__(self):
test_distributed_system.py CHANGED
@@ -9,6 +9,7 @@ import psutil
9
  import logging
10
  from offload_lib import discover_peers, matrix_multiply, prime_calculation, data_processing
11
  from your_tasks import complex_operation
 
12
 
13
  # إعداد السجل
14
  logging.basicConfig(
 
9
  import logging
10
  from offload_lib import discover_peers, matrix_multiply, prime_calculation, data_processing
11
  from your_tasks import complex_operation
12
+ from peer_discovery import PORT
13
 
14
  # إعداد السجل
15
  logging.basicConfig(
test_monitor.py CHANGED
@@ -7,6 +7,7 @@ import threading
7
  import psutil
8
  import signal
9
  import sys
 
10
 
11
  class TestMonitor:
12
  def __init__(self):
 
7
  import psutil
8
  import signal
9
  import sys
10
+ from peer_discovery import PORT
11
 
12
  class TestMonitor:
13
  def __init__(self):
video_processing.py CHANGED
@@ -7,6 +7,7 @@ import logging
7
  from functools import wraps
8
  from processor_manager import should_offload
9
  from remote_executor import execute_remotely
 
10
 
11
  logging.basicConfig(level=logging.INFO)
12
 
 
7
  from functools import wraps
8
  from processor_manager import should_offload
9
  from remote_executor import execute_remotely
10
+ from peer_discovery import PORT
11
 
12
  logging.basicConfig(level=logging.INFO)
13
 
your_tasks.py CHANGED
@@ -1,6 +1,7 @@
1
  import math
2
  import numpy as np
3
  from offload_lib import offload
 
4
 
5
  # الدوال الأساسية (محليّة)
6
  def prime_calculation(n: int):
 
1
  import math
2
  import numpy as np
3
  from offload_lib import offload
4
+ from peer_discovery import PORT
5
 
6
  # الدوال الأساسية (محليّة)
7
  def prime_calculation(n: int):