GitHub Action commited on
Commit
18163dc
·
1 Parent(s): 6d02891

Sync from GitHub with Git LFS

Browse files
agents/config.yml CHANGED
@@ -1,70 +1,46 @@
1
- # HMP Agent Configuration
2
-
3
- # === Общие параметры ===
4
- agent_id: "" # Оставьте пустым для генерации DiD автоматически
5
- agent_name: "CognitiveCore" # Имя агента
6
- agent_role: "core" # 'core' или 'shell'
7
-
8
- # === Прокси ===
9
- proxy_mode: false # false — прокси не используется, иначе true
10
- proxy_type: "socks5" # 'http', 'socks4', 'socks5' и т.д. (если proxy_mode: true)
11
- proxy_address: "127.0.0.1:9050"
12
-
13
- # === Функции ядра ===
14
- enable_llm: true # доступ к LLM
15
-
16
- serve_api: true # REST API
17
  api_port: 8080
18
-
19
- # === DHT-сеть и обмен знаниями ===
20
- dht_enabled: true # Включение участия в DHT-сети (включено принудительно!)
21
- dht_update: true # Регулярные обновления и публикация данных в DHT (включено принудительно!)
22
- bootstrap_responder: true # Агент отвечает на bootstrap-запросы (включено принудительно!)
23
- dht_port: 20784
24
- update_interval: 60 # секунд (для DHT-обновлений)
25
-
26
- # === LLM-бэкенды ===
 
 
 
27
  llm_backends:
28
- - name: "local-model"
29
- type: "local"
30
- path: "/models/gguf/mistral.gguf"
31
- format: "gguf"
32
- prompt_template: "mistral"
33
-
34
- - name: "lmstudio-local"
35
- type: "api"
36
- provider: "openai-compatible"
37
- model: "mistral" # или то, что LM Studio показывает как модель
38
- api_key: "lm-studio-any-key" # может быть заглушкой
39
- base_url: "http://127.0.0.1:1234/v1"
40
-
41
- - name: "openai-gpt4o"
42
- type: "api"
43
- provider: "openai"
44
- model: "gpt-4o"
45
- api_key: "sk-..."
46
-
47
- # Пользователь может добавить сколько угодно дополнительных локальных или сетевых LLM
48
-
49
- default_llm: "local-model" # если модели нет в списке `llm_backends` используется первая в списке
50
-
51
- # === Веб-интерфейс ===
52
- notebook_ui: true # UI в виде блокнота
53
- # ui_hosts:
54
- # - "0.0.0.0" # (небезопасно) доступ с любых IPv4-адресов
55
- # - "::" # (небезопасно) доступ с любых IPv6-адресов
56
- ui_hosts: # Какие IP прослушиваются, ["0.0.0.0"; "::"] - доступен везде
57
- - "127.0.0.1"
58
- - "::1"
59
  ui_port: 8765
60
-
61
- # === Данные пользователя ===
62
- default_user:
63
- username: "user"
64
- badges: "📌"
65
- email: "[email protected]"
66
- password: "password" # пусто при инициализации, будет установлен при регистрации
67
-
68
- # === Отладка и логгирование ===
69
- debug: true
70
- log_level: "INFO" # DEBUG, INFO, WARNING, ERROR
 
1
+ agent_id: did:hmp:4b2e20ef-a6c1-4605-897f-665140035494
2
+ agent_name: CognitiveCore
3
+ agent_role: core
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  api_port: 8080
5
+ bootstrap_responder: true
6
+ debug: true
7
+ default_llm: local-model
8
+ default_user:
9
+ badges: 📌
10
11
+ password: password
12
+ username: user
13
+ dht_enabled: true
14
+ dht_update: true
15
+ enable_llm: true
16
+ identity_agent: 4b2e20ef-a6c1-4605-897f-665140035494
17
  llm_backends:
18
+ - format: gguf
19
+ name: local-model
20
+ path: /models/gguf/mistral.gguf
21
+ prompt_template: mistral
22
+ type: local
23
+ - api_key: lm-studio-any-key
24
+ base_url: http://127.0.0.1:1234/v1
25
+ model: mistral
26
+ name: lmstudio-local
27
+ provider: openai-compatible
28
+ type: api
29
+ - api_key: sk-...
30
+ model: gpt-4o
31
+ name: openai-gpt4o
32
+ provider: openai
33
+ type: api
34
+ log_level: INFO
35
+ notebook_ui: true
36
+ proxy_address: 127.0.0.1:9050
37
+ proxy_mode: false
38
+ proxy_type: socks5
39
+ serve_api: true
40
+ tcp_port: 5000
41
+ udp_port: 4000
42
+ ui_hosts:
43
+ - 127.0.0.1
44
+ - ::1
 
 
 
 
45
  ui_port: 8765
46
+ update_interval: 60
 
 
 
 
 
 
 
 
 
 
agents/examples/config.yml CHANGED
@@ -20,7 +20,8 @@ api_port: 8080
20
  dht_enabled: true # Включение участия в DHT-сети (включено принудительно!)
21
  dht_update: true # Регулярные обновления и публикация данных в DHT (включено принудительно!)
22
  bootstrap_responder: true # Агент отвечает на bootstrap-запросы (включено принудительно!)
23
- dht_port: 20784
 
24
  update_interval: 60 # секунд (для DHT-обновлений)
25
 
26
  # === LLM-бэкенды ===
 
20
  dht_enabled: true # Включение участия в DHT-сети (включено принудительно!)
21
  dht_update: true # Регулярные обновления и публикация данных в DHT (включено принудительно!)
22
  bootstrap_responder: true # Агент отвечает на bootstrap-запросы (включено принудительно!)
23
+ udp_port: 4000
24
+ tcp_port: 5000
25
  update_interval: 60 # секунд (для DHT-обновлений)
26
 
27
  # === LLM-бэкенды ===
agents/peer_sync.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # agents/peer_sync.py
2
+
3
+ """
4
+ peer_sync.py — фоновый процесс синхронизации пиров в сети HMP
5
+ """
6
+
7
+ import socket
8
+ import threading
9
+ import time
10
+ import json
11
+ from tools.storage import Storage
12
+
13
+ storage = Storage()
14
+
15
+ # ======================
16
+ # UDP Discovery
17
+ # ======================
18
+
19
+ def udp_discovery_listener(udp_port: int):
20
+ """Слушаем UDP-пакеты"""
21
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
22
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
23
+ sock.bind(("", udp_port))
24
+
25
+ while True:
26
+ data, addr = sock.recvfrom(1024)
27
+ try:
28
+ msg = json.loads(data.decode("utf-8"))
29
+ peer_id = msg.get("id")
30
+ name = msg.get("name", "unknown")
31
+ addresses = msg.get("addresses", [f"{addr[0]}:{msg.get('tcp_port', udp_port)}"])
32
+ storage.add_or_update_peer(peer_id, name, addresses, source="discovery", status="online")
33
+ except Exception as e:
34
+ print("[PeerSync] Ошибка при обработке UDP пакета:", e)
35
+
36
+
37
+ def udp_discovery_sender(agent_id: str, agent_name: str, udp_port: int, tcp_port: int):
38
+ """Рассылаем UDP multicast/broadcast пакеты"""
39
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
40
+ sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
41
+
42
+ msg = {
43
+ "id": agent_id,
44
+ "name": agent_name,
45
+ "tcp_port": tcp_port,
46
+ "addresses": [f"127.0.0.1:{tcp_port}"]
47
+ }
48
+
49
+ last_broadcast = 0
50
+ DISCOVERY_INTERVAL = 60
51
+ BROADCAST_INTERVAL = 600
52
+
53
+ while True:
54
+ now = time.time()
55
+ # Multicast раз в минуту
56
+ if int(now) % DISCOVERY_INTERVAL == 0:
57
+ sock.sendto(json.dumps(msg).encode("utf-8"), ("239.255.0.1", udp_port))
58
+ # Broadcast раз в 10 минут
59
+ if now - last_broadcast > BROADCAST_INTERVAL:
60
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
61
+ sock.sendto(json.dumps(msg).encode("utf-8"), ("255.255.255.255", udp_port))
62
+ last_broadcast = now
63
+ time.sleep(1)
64
+
65
+
66
+ # ======================
67
+ # Peer Exchange (TCP)
68
+ # ======================
69
+
70
+ def peer_exchange():
71
+ """Периодический обмен списками пиров"""
72
+ PEER_EXCHANGE_INTERVAL = 120
73
+ while True:
74
+ peers = storage.get_online_peers(limit=50)
75
+ for peer in peers:
76
+ peer_id, addresses = peer["id"], peer["addresses"]
77
+ try:
78
+ addr = json.loads(addresses)[0]
79
+ host, port = addr.split(":")
80
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
81
+ s.settimeout(2)
82
+ s.connect((host, int(port)))
83
+ # пока только "каркас"
84
+ s.sendall(b"PEER_EXCHANGE_REQUEST")
85
+ s.close()
86
+ except Exception as e:
87
+ print(f"[PeerSync] Не удалось подключиться к {peer_id} ({addresses}): {e}")
88
+ time.sleep(PEER_EXCHANGE_INTERVAL)
89
+
90
+
91
+ # ======================
92
+ # Основной запуск
93
+ # ======================
94
+
95
+ def start_sync():
96
+ print("[PeerSync] Запуск фоновой синхронизации")
97
+
98
+ # 1. Конфиг
99
+ udp_port = int(storage.get_config_value("udp_port", 4000))
100
+ tcp_port = int(storage.get_config_value("tcp_port", 5000))
101
+ agent_id = storage.get_config_value("agent_id", "unknown-agent")
102
+ agent_name = storage.get_config_value("agent_name", "HMP-Agent")
103
+
104
+ # 2. Bootstrap загрузка
105
+ storage.load_bootstrap()
106
+
107
+ # 3. UDP discovery
108
+ threading.Thread(target=udp_discovery_listener, args=(udp_port,), daemon=True).start()
109
+ threading.Thread(target=udp_discovery_sender, args=(agent_id, agent_name, udp_port, tcp_port), daemon=True).start()
110
+
111
+ # 4. Peer exchange (TCP)
112
+ threading.Thread(target=peer_exchange, daemon=True).start()
113
+
114
+ # вечный цикл (чтобы поток не завершался)
115
+ while True:
116
+ time.sleep(60)
agents/start_repl.py CHANGED
@@ -16,7 +16,7 @@ storage = Storage()
16
  ENABLE_REPL = False # 🧠 repl.py
17
  ENABLE_UI = True # 📓 web_ui.py (FastAPI)
18
  ENABLE_MESH = False # 🌐 agent_mesh_listener.py
19
- ENABLE_SYNC = False # 🔄 peer_sync.py
20
  ENABLE_TRANSPORT = False # 📡 transporter.py
21
  ENABLE_CONTROL = False # 🧭 agent_controller.py
22
  ENABLE_CONTAINER = False # 🧱 container_agent.py
 
16
  ENABLE_REPL = False # 🧠 repl.py
17
  ENABLE_UI = True # 📓 web_ui.py (FastAPI)
18
  ENABLE_MESH = False # 🌐 agent_mesh_listener.py
19
+ ENABLE_SYNC = True # 🔄 peer_sync.py
20
  ENABLE_TRANSPORT = False # 📡 transporter.py
21
  ENABLE_CONTROL = False # 🧭 agent_controller.py
22
  ENABLE_CONTAINER = False # 🧱 container_agent.py
agents/tools/storage.py CHANGED
@@ -870,6 +870,49 @@ class Storage:
870
  }
871
  return None
872
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
873
  # Утилиты
874
 
875
  def close(self):
 
870
  }
871
  return None
872
 
873
+ # Работа с пирам (agent_peers)
874
+ def add_or_update_peer(self, peer_id, name, addresses, source="discovery", status="unknown"):
875
+ c = self.conn.cursor()
876
+ c.execute("""
877
+ INSERT INTO agent_peers (id, name, addresses, source, status, last_seen)
878
+ VALUES (?, ?, ?, ?, ?, ?)
879
+ ON CONFLICT(id) DO UPDATE SET
880
+ addresses=excluded.addresses,
881
+ source=excluded.source,
882
+ status=excluded.status,
883
+ last_seen=excluded.last_seen
884
+ """, (
885
+ peer_id,
886
+ name,
887
+ json.dumps(addresses),
888
+ source,
889
+ status,
890
+ datetime.now(UTC).isoformat()
891
+ ))
892
+ self.conn.commit()
893
+
894
+ def get_online_peers(self, limit=50):
895
+ c = self.conn.cursor()
896
+ c.execute("SELECT id, addresses FROM agent_peers WHERE status='online' LIMIT ?", (limit,))
897
+ return c.fetchall()
898
+
899
+ def load_bootstrap(self, bootstrap_file="bootstrap.txt"):
900
+ if not os.path.exists(bootstrap_file):
901
+ return
902
+ with open(bootstrap_file, "r", encoding="utf-8") as f:
903
+ for line in f:
904
+ line = line.strip()
905
+ if not line or line.startswith("#"):
906
+ continue
907
+ # Пример: http://node1.mesh.local:8000
908
+ try:
909
+ peer_url = line
910
+ peer_id = str(uuid.uuid4()) # временно генерим ID, потом можно подтянуть DID
911
+ name = peer_url.split("://")[1].split(":")[0]
912
+ self.add_or_update_peer(peer_id, name, [peer_url], source="bootstrap")
913
+ except Exception as e:
914
+ print(f"[Storage] Ошибка парсинга bootstrap: {line} -> {e}")
915
+
916
  # Утилиты
917
 
918
  def close(self):