GitHub Action commited on
Commit
b94a997
·
1 Parent(s): 697d40b

Sync from GitHub with Git LFS

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. agents/notebook/templates/login.html +4 -0
  2. agents/notebook/templates/messages.html +2 -4
  3. agents/notebook/templates/register.html +4 -0
  4. agents/notebook/views.py +15 -9
  5. agents/web_ui.py +0 -2
  6. hf_repo/hf_repo/agents/notebook/templates/login.html +10 -6
  7. hf_repo/hf_repo/agents/notebook/templates/messages.html +1 -1
  8. hf_repo/hf_repo/agents/notebook/templates/register.html +11 -7
  9. hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py +7 -7
  10. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml +65 -40
  11. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/login.html +1 -0
  12. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/register.html +1 -0
  13. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml +40 -65
  14. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/login.html +5 -14
  15. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html +9 -2
  16. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/register.html +6 -14
  17. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/views.py +36 -30
  18. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py +26 -19
  19. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/login.html +14 -0
  20. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html +40 -8
  21. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/register.html +14 -0
  22. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/views.py +72 -11
  23. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/requirements.txt +2 -1
  24. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py +76 -11
  25. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/web_ui.py +3 -0
  26. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/add_message.py +5 -9
  27. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/views.py +3 -5
  28. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/db_structure.sql +1 -1
  29. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py +5 -5
  30. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/readme.md +1 -1
  31. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/readme.md +1 -2
  32. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml +65 -40
  33. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/check_agents.py +19 -5
  34. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml +40 -71
  35. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/examples/config.yml +1 -7
  36. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/init.py +17 -26
  37. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/logger.py +3 -3
  38. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/mcp_server.py +2 -2
  39. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/repl.py +2 -2
  40. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/context_builder.py +2 -2
  41. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/identity.py +3 -3
  42. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/memory_utils.py +3 -3
  43. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py +11 -10
  44. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/web_ui.py +1 -2
  45. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/start_repl.py +4 -0
  46. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py +7 -2
  47. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/web_ui.py +5 -3
  48. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/check_agents.bat +12 -0
  49. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/check_agents.sh +11 -0
  50. hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/check_agents.bat +12 -0
agents/notebook/templates/login.html CHANGED
@@ -1,3 +1,7 @@
 
 
 
 
1
  <table>
2
  <caption>Вход</caption>
3
  <form method="post">
 
1
+ {% if error %}
2
+ <p style="color:red">{{ error }}</p>
3
+ {% endif %}
4
+
5
  <table>
6
  <caption>Вход</caption>
7
  <form method="post">
agents/notebook/templates/messages.html CHANGED
@@ -25,10 +25,8 @@
25
 
26
  <form method="post">
27
  <textarea name="text" rows="3" cols="40" placeholder="Введите сообщение..."></textarea><br>
28
- <label>
29
- <input type="checkbox" name="hidden"> Скрыто
30
- </label>
31
- <button type="submit">Отправить</button>
32
  </form>
33
 
34
  <hr>
 
25
 
26
  <form method="post">
27
  <textarea name="text" rows="3" cols="40" placeholder="Введите сообщение..."></textarea><br>
28
+ <button name="hidden" value="false" type="submit">Отправить</button>
29
+ <button name="hidden" value="true" type="submit">Отправить приватно</button>
 
 
30
  </form>
31
 
32
  <hr>
agents/notebook/templates/register.html CHANGED
@@ -1,3 +1,7 @@
 
 
 
 
1
  <table>
2
  <caption>Регистрация</caption>
3
  <form method="post">
 
1
+ {% if error %}
2
+ <p style="color:red">{{ error }}</p>
3
+ {% endif %}
4
+
5
  <table>
6
  <caption>Регистрация</caption>
7
  <form method="post">
agents/notebook/views.py CHANGED
@@ -1,3 +1,5 @@
 
 
1
  from fastapi import APIRouter, Request, Form
2
  from fastapi.responses import RedirectResponse
3
  from fastapi.templating import Jinja2Templates
@@ -43,7 +45,10 @@ def show_messages(request: Request, only_personal: bool = False):
43
  if not did:
44
  return RedirectResponse("/login", status_code=303)
45
 
46
- is_operator = False # Пока не реализовано
 
 
 
47
  messages = storage.get_notes(
48
  limit=50,
49
  user_did=did,
@@ -61,17 +66,18 @@ def show_messages(request: Request, only_personal: bool = False):
61
  def post_message(
62
  request: Request,
63
  text: str = Form(...),
64
- hidden: str = Form(default=None)
65
  ):
66
  did = request.session.get("did", "anon")
67
- is_hidden = 1 if hidden else 0
68
 
69
- storage.write_note(
70
- content=text,
71
- user_did=did,
72
- source="user",
73
- hidden=is_hidden
74
- )
 
75
  return RedirectResponse(url="/messages", status_code=303)
76
 
77
  @router.get("/login")
 
1
+ # agents/notebook/views.py
2
+
3
  from fastapi import APIRouter, Request, Form
4
  from fastapi.responses import RedirectResponse
5
  from fastapi.templating import Jinja2Templates
 
45
  if not did:
46
  return RedirectResponse("/login", status_code=303)
47
 
48
+ # Получаем инфу о пользователе, чтобы понять, оператор ли он
49
+ user_info = storage.get_user_info_by_did(did)
50
+ is_operator = bool(user_info and user_info.get("operator"))
51
+
52
  messages = storage.get_notes(
53
  limit=50,
54
  user_did=did,
 
66
  def post_message(
67
  request: Request,
68
  text: str = Form(...),
69
+ hidden: str = Form(default="false")
70
  ):
71
  did = request.session.get("did", "anon")
72
+ is_hidden = 1 if hidden.lower() == "true" else 0
73
 
74
+ if text.strip():
75
+ storage.write_note(
76
+ content=text.strip(),
77
+ user_did=did,
78
+ source="user",
79
+ hidden=is_hidden
80
+ )
81
  return RedirectResponse(url="/messages", status_code=303)
82
 
83
  @router.get("/login")
agents/web_ui.py CHANGED
@@ -12,7 +12,6 @@ process_name = os.path.splitext(os.path.basename(__file__))[0]
12
  from fastapi import FastAPI
13
  from fastapi.staticfiles import StaticFiles
14
  from fastapi.templating import Jinja2Templates
15
- #from agents.notebook.auth import router as auth_router
16
  from starlette.middleware.sessions import SessionMiddleware
17
  from agents.notebook.views import router as notebook_router
18
  from tools.storage import Storage
@@ -25,7 +24,6 @@ app.add_middleware(SessionMiddleware, secret_key="очень_секретный_
25
  app.mount("/static", StaticFiles(directory=os.path.join(os.path.dirname(__file__), "notebook/static")), name="static")
26
  templates = Jinja2Templates(directory=os.path.join(os.path.dirname(__file__), "notebook/templates"))
27
 
28
- #app.include_router(auth_router)
29
  app.include_router(notebook_router)
30
 
31
  @app.on_event("startup")
 
12
  from fastapi import FastAPI
13
  from fastapi.staticfiles import StaticFiles
14
  from fastapi.templating import Jinja2Templates
 
15
  from starlette.middleware.sessions import SessionMiddleware
16
  from agents.notebook.views import router as notebook_router
17
  from tools.storage import Storage
 
24
  app.mount("/static", StaticFiles(directory=os.path.join(os.path.dirname(__file__), "notebook/static")), name="static")
25
  templates = Jinja2Templates(directory=os.path.join(os.path.dirname(__file__), "notebook/templates"))
26
 
 
27
  app.include_router(notebook_router)
28
 
29
  @app.on_event("startup")
hf_repo/hf_repo/agents/notebook/templates/login.html CHANGED
@@ -1,6 +1,10 @@
1
- <form method="post">
2
- <label>Email: <input type="email" name="mail" required></label><br>
3
- <label>Пароль: <input type="password" name="password" required></label><br>
4
- <button type="submit">Войти</button>
5
- </form>
6
- Нет учетки: <a href="/register">зарегистрироваться</a>
 
 
 
 
 
1
+ <table>
2
+ <caption>Вход</caption>
3
+ <form method="post">
4
+ <tr><th><label>Email:</th><td><input type="email" name="mail" required></label></td></tr>
5
+ <tr><th><label>Пароль:</th><td><input type="password" name="password" required></label></td></tr>
6
+ <tr><th colspan="2"><button type="submit">Войти</button></th></tr>
7
+ </form>
8
+ </table>
9
+
10
+ <hr>Нет учетки: <a href="/register">Зарегистрироваться</a>
hf_repo/hf_repo/agents/notebook/templates/messages.html CHANGED
@@ -27,7 +27,7 @@
27
  <textarea name="text" rows="3" cols="40" placeholder="Введите сообщение..."></textarea><br>
28
  <label>
29
  <input type="checkbox" name="hidden"> Скрыто
30
- </label><br>
31
  <button type="submit">Отправить</button>
32
  </form>
33
 
 
27
  <textarea name="text" rows="3" cols="40" placeholder="Введите сообщение..."></textarea><br>
28
  <label>
29
  <input type="checkbox" name="hidden"> Скрыто
30
+ </label>
31
  <button type="submit">Отправить</button>
32
  </form>
33
 
hf_repo/hf_repo/agents/notebook/templates/register.html CHANGED
@@ -1,7 +1,11 @@
1
- <form method="post">
2
- <label>Имя пользователя: <input type="text" name="username" required></label><br>
3
- <label>Email: <input type="email" name="mail" required></label><br>
4
- <label>Пароль: <input type="password" name="password" required></label><br>
5
- <button type="submit">Зарегистрироваться</button>
6
- </form>
7
- Есть учетка: <a href="/login">войти</a>
 
 
 
 
 
1
+ <table>
2
+ <caption>Регистрация</caption>
3
+ <form method="post">
4
+ <tr><th><label>Имя:</th><td><input type="text" name="username" required></label></td></tr>
5
+ <tr><th><label>Email:</th><td><input type="email" name="mail" required></label></td></tr>
6
+ <tr><th><label>Пароль:</th><td><input type="password" name="password" required></label></td></tr>
7
+ <tr><th colspan="2"><button type="submit">Зарегистрироваться</button></th></tr>
8
+ </form>
9
+ </table>
10
+
11
+ <hr>Есть учетка: <a href="/login">Войти</a>
hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py CHANGED
@@ -7,6 +7,9 @@ import json
7
  import uuid
8
 
9
  from datetime import datetime, timedelta, UTC
 
 
 
10
 
11
  SCRIPTS_BASE_PATH = "scripts"
12
 
@@ -747,21 +750,18 @@ class Storage:
747
  return [dict(row) for row in cursor.fetchall()]
748
 
749
  # Пользователи
750
- def _hash_password(self, password: str) -> str:
751
- return hashlib.sha256(password.encode()).hexdigest()
752
-
753
  def register_user(self, username: str, mail: str, password: str) -> bool:
754
  mail = mail.lower()
755
- did = f"did:example:{uuid.uuid4()}"
756
  try:
757
  self.conn.execute(
758
  "INSERT INTO users (username, mail, password_hash, did) VALUES (?, ?, ?, ?)",
759
- (username, mail, self._hash_password(password), did)
760
  )
761
  self.conn.commit()
762
  return True
763
  except sqlite3.IntegrityError:
764
- return False # уже существует (уникальность mail или did)
765
 
766
  def authenticate_user(self, mail: str, password: str) -> bool:
767
  mail = mail.lower()
@@ -772,7 +772,7 @@ class Storage:
772
  )
773
  result = cursor.fetchone()
774
  if result:
775
- return result["password_hash"] == self._hash_password(password)
776
  return False
777
 
778
  def get_user_info(self, mail: str) -> dict | None:
 
7
  import uuid
8
 
9
  from datetime import datetime, timedelta, UTC
10
+ from werkzeug.security import generate_password_hash, check_password_hash
11
+ from tools.identity import generate_did
12
+ from tools.crypto import generate_keypair
13
 
14
  SCRIPTS_BASE_PATH = "scripts"
15
 
 
750
  return [dict(row) for row in cursor.fetchall()]
751
 
752
  # Пользователи
 
 
 
753
  def register_user(self, username: str, mail: str, password: str) -> bool:
754
  mail = mail.lower()
755
+ did = generate_did()
756
  try:
757
  self.conn.execute(
758
  "INSERT INTO users (username, mail, password_hash, did) VALUES (?, ?, ?, ?)",
759
+ (username, mail, generate_password_hash(password), did)
760
  )
761
  self.conn.commit()
762
  return True
763
  except sqlite3.IntegrityError:
764
+ return False
765
 
766
  def authenticate_user(self, mail: str, password: str) -> bool:
767
  mail = mail.lower()
 
772
  )
773
  result = cursor.fetchone()
774
  if result:
775
+ return check_password_hash(result["password_hash"], password)
776
  return False
777
 
778
  def get_user_info(self, mail: str) -> dict | None:
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml CHANGED
@@ -1,44 +1,69 @@
1
- agent_id: did:hmp:dac57687-1839-423d-8624-c38324de2635
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
10
- password: password
11
- username: user
12
- dht_enabled: true
13
  dht_port: 20784
14
- dht_update: true
15
- enable_llm: true
16
- identity_agent: dac57687-1839-423d-8624-c38324de2635
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
- ui_hosts:
41
- - 127.0.0.1
42
- - ::1
 
 
 
 
 
 
43
  ui_port: 8765
44
- update_interval: 60
 
 
 
 
 
 
 
 
 
 
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
+ email: "[email protected]"
65
+ password: "password" # пусто при инициализации, будет установлен при регистрации
66
+
67
+ # === Отладка и логгирование ===
68
+ debug: true
69
+ log_level: "INFO" # DEBUG, INFO, WARNING, ERROR
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/login.html CHANGED
@@ -3,3 +3,4 @@
3
  <label>Пароль: <input type="password" name="password" required></label><br>
4
  <button type="submit">Войти</button>
5
  </form>
 
 
3
  <label>Пароль: <input type="password" name="password" required></label><br>
4
  <button type="submit">Войти</button>
5
  </form>
6
+ Нет учетки: <a href="/register">зарегистрироваться</a>
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/register.html CHANGED
@@ -4,3 +4,4 @@
4
  <label>Пароль: <input type="password" name="password" required></label><br>
5
  <button type="submit">Зарегистрироваться</button>
6
  </form>
 
 
4
  <label>Пароль: <input type="password" name="password" required></label><br>
5
  <button type="submit">Зарегистрироваться</button>
6
  </form>
7
+ Есть учетка: <a href="/login">войти</a>
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml CHANGED
@@ -1,69 +1,44 @@
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
- email: "[email protected]"
65
- password: "password" # пусто при инициализации, будет установлен при регистрации
66
-
67
- # === Отладка и логгирование ===
68
- debug: true
69
- log_level: "INFO" # DEBUG, INFO, WARNING, ERROR
 
1
+ agent_id: did:hmp:dac57687-1839-423d-8624-c38324de2635
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
10
+ password: password
11
+ username: user
12
+ dht_enabled: true
13
  dht_port: 20784
14
+ dht_update: true
15
+ enable_llm: true
16
+ identity_agent: dac57687-1839-423d-8624-c38324de2635
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
+ ui_hosts:
41
+ - 127.0.0.1
42
+ - ::1
 
 
 
 
 
 
43
  ui_port: 8765
44
+ update_interval: 60
 
 
 
 
 
 
 
 
 
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/login.html CHANGED
@@ -1,14 +1,5 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head><title>Вход</title></head>
4
- <body>
5
- <h2>Вход</h2>
6
- {% if error %}<p style="color: red">{{ error }}</p>{% endif %}
7
- <form method="post">
8
- <input name="username" placeholder="Имя пользователя">
9
- <input name="password" type="password" placeholder="Пароль">
10
- <button type="submit">Войти</button>
11
- </form>
12
- <p>Нет аккаунта? <a href="/register">Регистрация</a></p>
13
- </body>
14
- </html>
 
1
+ <form method="post">
2
+ <label>Email: <input type="email" name="mail" required></label><br>
3
+ <label>Пароль: <input type="password" name="password" required></label><br>
4
+ <button type="submit">Войти</button>
5
+ </form>
 
 
 
 
 
 
 
 
 
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html CHANGED
@@ -20,11 +20,14 @@
20
  <a href="/login">Войти</a> | <a href="/register">Регистрация</a>
21
  {% endif %}
22
  </div>
 
23
  <h1>Сообщения</h1>
24
 
25
  <form method="post">
26
  <textarea name="text" rows="3" cols="40" placeholder="Введите сообщение..."></textarea><br>
27
- <input type="text" name="user_did" placeholder="User DID" readonly value="{{ username }}">
 
 
28
  <button type="submit">Отправить</button>
29
  </form>
30
 
@@ -38,11 +41,15 @@
38
  <hr>
39
 
40
  {% for msg in messages %}
41
- <div class="message source-{{ msg.source }} {% if msg.user_did == 'did:example:local-user' %}from-self{% endif %}">
42
  <div>
43
  <strong>{{ msg.source }}</strong> — {{ msg.timestamp }}
44
  {% if msg.hidden %}<span class="private"></span>{% endif %}
45
  </div>
 
 
 
 
46
  <div>{{ msg.text }}</div>
47
  </div>
48
  {% endfor %}
 
20
  <a href="/login">Войти</a> | <a href="/register">Регистрация</a>
21
  {% endif %}
22
  </div>
23
+
24
  <h1>Сообщения</h1>
25
 
26
  <form method="post">
27
  <textarea name="text" rows="3" cols="40" placeholder="Введите сообщение..."></textarea><br>
28
+ <label>
29
+ <input type="checkbox" name="hidden"> Скрыто
30
+ </label><br>
31
  <button type="submit">Отправить</button>
32
  </form>
33
 
 
41
  <hr>
42
 
43
  {% for msg in messages %}
44
+ <div class="message source-{{ msg.source }} {% if msg.user_did == request.session['did'] %}from-self{% endif %}">
45
  <div>
46
  <strong>{{ msg.source }}</strong> — {{ msg.timestamp }}
47
  {% if msg.hidden %}<span class="private"></span>{% endif %}
48
  </div>
49
+ <div>
50
+ от {{ msg.user_did[:10] }}...
51
+ {% if msg.username %}({{ msg.username }}){% endif %}
52
+ </div>
53
  <div>{{ msg.text }}</div>
54
  </div>
55
  {% endfor %}
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/register.html CHANGED
@@ -1,14 +1,6 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head><title>Регистрация</title></head>
4
- <body>
5
- <h2>Регистрация</h2>
6
- {% if error %}<p style="color: red">{{ error }}</p>{% endif %}
7
- <form method="post">
8
- <input name="username" placeholder="Имя пользователя">
9
- <input name="password" type="password" placeholder="Пароль">
10
- <button type="submit">Зарегистрироваться</button>
11
- </form>
12
- <p>Уже есть аккаунт? <a href="/login">Войти</a></p>
13
- </body>
14
- </html>
 
1
+ <form method="post">
2
+ <label>Имя пользователя: <input type="text" name="username" required></label><br>
3
+ <label>Email: <input type="email" name="mail" required></label><br>
4
+ <label>Пароль: <input type="password" name="password" required></label><br>
5
+ <button type="submit">Зарегистрироваться</button>
6
+ </form>
 
 
 
 
 
 
 
 
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/views.py CHANGED
@@ -1,14 +1,8 @@
1
- # agents/notebook/views.py
2
-
3
- from fastapi import APIRouter, Request, Form, Depends
4
  from fastapi.responses import RedirectResponse
5
  from fastapi.templating import Jinja2Templates
6
- from fastapi.exceptions import HTTPException
7
- from starlette.middleware.sessions import SessionMiddleware
8
  from starlette.status import HTTP_303_SEE_OTHER
9
  from tools.storage import Storage
10
- from passlib.hash import bcrypt
11
- from fastapi import FastAPI
12
 
13
  router = APIRouter()
14
  templates = Jinja2Templates(directory="notebook/templates")
@@ -16,13 +10,14 @@ storage = Storage()
16
 
17
  @router.get("/chat")
18
  def chat_page(request: Request):
19
- username = request.session.get("user")
20
- if not username:
 
21
  return RedirectResponse("/login", status_code=303)
22
 
23
  notes = storage.fetchall(
24
  "SELECT text, timestamp, source FROM notes WHERE hidden=0 AND user_did=? ORDER BY timestamp DESC LIMIT 20",
25
- (username,)
26
  )
27
  return templates.TemplateResponse("chat.html", {
28
  "request": request,
@@ -32,24 +27,26 @@ def chat_page(request: Request):
32
 
33
  @router.post("/chat")
34
  def submit_note(request: Request, message: str = Form(...)):
35
- username = request.session.get("user", "anon") # Можно вернуть anon, если не залогинен
36
  if message.strip():
37
- storage.execute(
38
- "INSERT INTO notes (text, source, user_did) VALUES (?, ?, ?)",
39
- (message.strip(), "user", username)
 
40
  )
41
  return RedirectResponse(url="/chat", status_code=303)
42
 
43
  @router.get("/messages")
44
  def show_messages(request: Request, only_personal: bool = False):
45
- username = request.session.get("user")
46
- if not username:
 
47
  return RedirectResponse("/login", status_code=303)
48
 
49
  is_operator = False # Пока не реализовано
50
  messages = storage.get_notes(
51
  limit=50,
52
- user_did=username,
53
  is_operator=is_operator,
54
  only_personal=only_personal
55
  )
@@ -57,21 +54,21 @@ def show_messages(request: Request, only_personal: bool = False):
57
  "request": request,
58
  "messages": messages,
59
  "only_personal": only_personal,
60
- "username": username # 👈 вот это
61
  })
62
 
63
  @router.post("/messages")
64
  def post_message(
65
  request: Request,
66
  text: str = Form(...),
67
- user_did: str = Form(default="anon"),
68
  hidden: str = Form(default=None)
69
  ):
 
70
  is_hidden = 1 if hidden else 0
71
 
72
  storage.write_note(
73
  content=text,
74
- user_did=user_did,
75
  source="user",
76
  hidden=is_hidden
77
  )
@@ -82,13 +79,15 @@ def login_page(request: Request):
82
  return templates.TemplateResponse("login.html", {"request": request})
83
 
84
  @router.post("/login")
85
- def login_user(request: Request, username: str = Form(...), password: str = Form(...)):
86
- if storage.authenticate_user(username, password):
87
- request.session["user"] = username
88
- return RedirectResponse("/chat", status_code=HTTP_303_SEE_OTHER)
 
 
89
  return templates.TemplateResponse("login.html", {
90
  "request": request,
91
- "error": "Неверный логин или пароль"
92
  })
93
 
94
  @router.get("/register")
@@ -96,13 +95,20 @@ def register_page(request: Request):
96
  return templates.TemplateResponse("register.html", {"request": request})
97
 
98
  @router.post("/register")
99
- def register_user(request: Request, username: str = Form(...), password: str = Form(...)):
100
- if storage.register_user(username, password):
101
- request.session["user"] = username
102
- return RedirectResponse("/chat", status_code=HTTP_303_SEE_OTHER)
 
 
 
 
 
 
 
103
  return templates.TemplateResponse("register.html", {
104
  "request": request,
105
- "error": "Пользователь уже существует"
106
  })
107
 
108
  @router.get("/logout")
 
1
+ from fastapi import APIRouter, Request, Form
 
 
2
  from fastapi.responses import RedirectResponse
3
  from fastapi.templating import Jinja2Templates
 
 
4
  from starlette.status import HTTP_303_SEE_OTHER
5
  from tools.storage import Storage
 
 
6
 
7
  router = APIRouter()
8
  templates = Jinja2Templates(directory="notebook/templates")
 
10
 
11
  @router.get("/chat")
12
  def chat_page(request: Request):
13
+ did = request.session.get("did")
14
+ username = request.session.get("username")
15
+ if not did:
16
  return RedirectResponse("/login", status_code=303)
17
 
18
  notes = storage.fetchall(
19
  "SELECT text, timestamp, source FROM notes WHERE hidden=0 AND user_did=? ORDER BY timestamp DESC LIMIT 20",
20
+ (did,)
21
  )
22
  return templates.TemplateResponse("chat.html", {
23
  "request": request,
 
27
 
28
  @router.post("/chat")
29
  def submit_note(request: Request, message: str = Form(...)):
30
+ did = request.session.get("did", "anon")
31
  if message.strip():
32
+ storage.write_note(
33
+ content=message.strip(),
34
+ user_did=did,
35
+ source="user"
36
  )
37
  return RedirectResponse(url="/chat", status_code=303)
38
 
39
  @router.get("/messages")
40
  def show_messages(request: Request, only_personal: bool = False):
41
+ did = request.session.get("did")
42
+ username = request.session.get("username")
43
+ if not did:
44
  return RedirectResponse("/login", status_code=303)
45
 
46
  is_operator = False # Пока не реализовано
47
  messages = storage.get_notes(
48
  limit=50,
49
+ user_did=did,
50
  is_operator=is_operator,
51
  only_personal=only_personal
52
  )
 
54
  "request": request,
55
  "messages": messages,
56
  "only_personal": only_personal,
57
+ "username": username
58
  })
59
 
60
  @router.post("/messages")
61
  def post_message(
62
  request: Request,
63
  text: str = Form(...),
 
64
  hidden: str = Form(default=None)
65
  ):
66
+ did = request.session.get("did", "anon")
67
  is_hidden = 1 if hidden else 0
68
 
69
  storage.write_note(
70
  content=text,
71
+ user_did=did,
72
  source="user",
73
  hidden=is_hidden
74
  )
 
79
  return templates.TemplateResponse("login.html", {"request": request})
80
 
81
  @router.post("/login")
82
+ def login_user(request: Request, mail: str = Form(...), password: str = Form(...)):
83
+ if storage.authenticate_user(mail, password):
84
+ user_info = storage.get_user_info(mail)
85
+ request.session["username"] = user_info["username"]
86
+ request.session["did"] = user_info["did"]
87
+ return RedirectResponse("/messages", status_code=HTTP_303_SEE_OTHER)
88
  return templates.TemplateResponse("login.html", {
89
  "request": request,
90
+ "error": "Неверный email или пароль"
91
  })
92
 
93
  @router.get("/register")
 
95
  return templates.TemplateResponse("register.html", {"request": request})
96
 
97
  @router.post("/register")
98
+ def register_user(
99
+ request: Request,
100
+ username: str = Form(...),
101
+ mail: str = Form(...),
102
+ password: str = Form(...)
103
+ ):
104
+ if storage.register_user(username, mail, password):
105
+ user_info = storage.get_user_info(mail)
106
+ request.session["username"] = user_info["username"]
107
+ request.session["did"] = user_info["did"]
108
+ return RedirectResponse("/messages", status_code=HTTP_303_SEE_OTHER)
109
  return templates.TemplateResponse("register.html", {
110
  "request": request,
111
+ "error": "Пользователь с таким email уже существует"
112
  })
113
 
114
  @router.get("/logout")
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py CHANGED
@@ -4,6 +4,7 @@ import hashlib
4
  import sqlite3
5
  import os
6
  import json
 
7
 
8
  from datetime import datetime, timedelta, UTC
9
 
@@ -17,7 +18,6 @@ class Storage:
17
  self.conn = sqlite3.connect(db_path, check_same_thread=False)
18
  self.conn.row_factory = sqlite3.Row
19
  self._init_db()
20
- self._init_user_table()
21
 
22
  def _init_db(self):
23
  # Загружаем и выполняем весь SQL из файла db_structure.sql
@@ -750,39 +750,46 @@ class Storage:
750
  def _hash_password(self, password: str) -> str:
751
  return hashlib.sha256(password.encode()).hexdigest()
752
 
753
- def _init_user_table(self):
754
- self.conn.execute('''
755
- CREATE TABLE IF NOT EXISTS users (
756
- id INTEGER PRIMARY KEY AUTOINCREMENT,
757
- username TEXT UNIQUE NOT NULL,
758
- password_hash TEXT NOT NULL
759
- )
760
- ''')
761
- self.conn.commit()
762
-
763
- def register_user(self, username: str, password: str) -> bool:
764
- self._init_user_table()
765
  try:
766
  self.conn.execute(
767
- "INSERT INTO users (username, password_hash) VALUES (?, ?)",
768
- (username, self._hash_password(password))
769
  )
770
  self.conn.commit()
771
  return True
772
  except sqlite3.IntegrityError:
773
- return False # пользователь уже существует
774
 
775
- def authenticate_user(self, username: str, password: str) -> bool:
 
776
  cursor = self.conn.cursor()
777
  cursor.execute(
778
- "SELECT password_hash FROM users WHERE username = ?",
779
- (username,)
780
  )
781
  result = cursor.fetchone()
782
  if result:
783
  return result["password_hash"] == self._hash_password(password)
784
  return False
785
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
786
  # Утилиты
787
 
788
  def close(self):
 
4
  import sqlite3
5
  import os
6
  import json
7
+ import uuid
8
 
9
  from datetime import datetime, timedelta, UTC
10
 
 
18
  self.conn = sqlite3.connect(db_path, check_same_thread=False)
19
  self.conn.row_factory = sqlite3.Row
20
  self._init_db()
 
21
 
22
  def _init_db(self):
23
  # Загружаем и выполняем весь SQL из файла db_structure.sql
 
750
  def _hash_password(self, password: str) -> str:
751
  return hashlib.sha256(password.encode()).hexdigest()
752
 
753
+ def register_user(self, username: str, mail: str, password: str) -> bool:
754
+ mail = mail.lower()
755
+ did = f"did:example:{uuid.uuid4()}"
 
 
 
 
 
 
 
 
 
756
  try:
757
  self.conn.execute(
758
+ "INSERT INTO users (username, mail, password_hash, did) VALUES (?, ?, ?, ?)",
759
+ (username, mail, self._hash_password(password), did)
760
  )
761
  self.conn.commit()
762
  return True
763
  except sqlite3.IntegrityError:
764
+ return False # уже существует (уникальность mail или did)
765
 
766
+ def authenticate_user(self, mail: str, password: str) -> bool:
767
+ mail = mail.lower()
768
  cursor = self.conn.cursor()
769
  cursor.execute(
770
+ "SELECT password_hash FROM users WHERE mail = ?",
771
+ (mail,)
772
  )
773
  result = cursor.fetchone()
774
  if result:
775
  return result["password_hash"] == self._hash_password(password)
776
  return False
777
 
778
+ def get_user_info(self, mail: str) -> dict | None:
779
+ mail = mail.lower()
780
+ cursor = self.conn.cursor()
781
+ cursor.execute(
782
+ "SELECT username, did FROM users WHERE mail = ?",
783
+ (mail,)
784
+ )
785
+ result = cursor.fetchone()
786
+ if result:
787
+ return {
788
+ "username": result["username"],
789
+ "did": result["did"]
790
+ }
791
+ return None
792
+
793
  # Утилиты
794
 
795
  def close(self):
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/login.html ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head><title>Вход</title></head>
4
+ <body>
5
+ <h2>Вход</h2>
6
+ {% if error %}<p style="color: red">{{ error }}</p>{% endif %}
7
+ <form method="post">
8
+ <input name="username" placeholder="Имя пользователя">
9
+ <input name="password" type="password" placeholder="Пароль">
10
+ <button type="submit">Войти</button>
11
+ </form>
12
+ <p>Нет аккаунта? <a href="/register">Регистрация</a></p>
13
+ </body>
14
+ </html>
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html CHANGED
@@ -1,18 +1,50 @@
1
- <!-- templates/messages.html -->
2
  <!DOCTYPE html>
3
  <html>
4
  <head>
5
- <title>Отправка сообщения агенту</title>
 
 
 
 
 
 
 
 
 
6
  </head>
7
  <body>
8
- <h2>Новое сообщение</h2>
9
- <form method="post" action="/messages">
10
- <label for="text">Сообщение:</label><br>
11
- <textarea name="text" rows="4" cols="50" required></textarea><br><br>
12
-
13
- <label><input type="checkbox" name="is_private" value="true"> Приватное сообщение</label><br><br>
 
 
14
 
 
 
 
15
  <button type="submit">Отправить</button>
16
  </form>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  </body>
18
  </html>
 
 
1
  <!DOCTYPE html>
2
  <html>
3
  <head>
4
+ <title>Сообщения</title>
5
+ <style>
6
+ .message { padding: 8px; margin: 10px 0; border-radius: 8px; }
7
+ .source-user { background-color: #e0f7fa; }
8
+ .source-cli { background-color: #dcedc8; }
9
+ .source-llm { background-color: #f3e5f5; }
10
+ .source-system { background-color: #fff3e0; }
11
+ .private::after { content: " 🔒"; }
12
+ .from-self::before { content: "🧍 "; }
13
+ </style>
14
  </head>
15
  <body>
16
+ <div style="margin-bottom: 10px;">
17
+ {% if username %}
18
+ Привет, {{ username }} | <a href="/logout">Выход</a>
19
+ {% else %}
20
+ <a href="/login">Войти</a> | <a href="/register">Регистрация</a>
21
+ {% endif %}
22
+ </div>
23
+ <h1>Сообщения</h1>
24
 
25
+ <form method="post">
26
+ <textarea name="text" rows="3" cols="40" placeholder="Введите сообщение..."></textarea><br>
27
+ <input type="text" name="user_did" placeholder="User DID" readonly value="{{ username }}">
28
  <button type="submit">Отправить</button>
29
  </form>
30
+
31
+ <hr>
32
+
33
+ <div>
34
+ <a href="/messages">📢 Все сообщения</a> |
35
+ <a href="/messages?only_personal=true">🙋 Только мои</a>
36
+ </div>
37
+
38
+ <hr>
39
+
40
+ {% for msg in messages %}
41
+ <div class="message source-{{ msg.source }} {% if msg.user_did == 'did:example:local-user' %}from-self{% endif %}">
42
+ <div>
43
+ <strong>{{ msg.source }}</strong> — {{ msg.timestamp }}
44
+ {% if msg.hidden %}<span class="private"></span>{% endif %}
45
+ </div>
46
+ <div>{{ msg.text }}</div>
47
+ </div>
48
+ {% endfor %}
49
  </body>
50
  </html>
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/register.html ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head><title>Регистрация</title></head>
4
+ <body>
5
+ <h2>Регистрация</h2>
6
+ {% if error %}<p style="color: red">{{ error }}</p>{% endif %}
7
+ <form method="post">
8
+ <input name="username" placeholder="Имя пользователя">
9
+ <input name="password" type="password" placeholder="Пароль">
10
+ <button type="submit">Зарегистрироваться</button>
11
+ </form>
12
+ <p>Уже есть аккаунт? <a href="/login">Войти</a></p>
13
+ </body>
14
+ </html>
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/views.py CHANGED
@@ -1,50 +1,111 @@
1
  # agents/notebook/views.py
2
 
3
- from fastapi import APIRouter, Request, Form
4
  from fastapi.responses import RedirectResponse
5
  from fastapi.templating import Jinja2Templates
 
 
 
6
  from tools.storage import Storage
 
 
7
 
8
  router = APIRouter()
9
  templates = Jinja2Templates(directory="notebook/templates")
10
  storage = Storage()
11
 
12
- DID = "did:example:local-user" # временно
13
-
14
  @router.get("/chat")
15
  def chat_page(request: Request):
 
 
 
 
16
  notes = storage.fetchall(
17
  "SELECT text, timestamp, source FROM notes WHERE hidden=0 AND user_did=? ORDER BY timestamp DESC LIMIT 20",
18
- (DID,)
19
  )
20
- return templates.TemplateResponse("chat.html", {"request": request, "notes": notes})
 
 
 
 
21
 
22
  @router.post("/chat")
23
  def submit_note(request: Request, message: str = Form(...)):
 
24
  if message.strip():
25
  storage.execute(
26
  "INSERT INTO notes (text, source, user_did) VALUES (?, ?, ?)",
27
- (message.strip(), "user", DID)
28
  )
29
  return RedirectResponse(url="/chat", status_code=303)
30
 
31
  @router.get("/messages")
32
- def show_messages(request: Request):
33
- messages = storage.get_notes(limit=50)
 
 
 
 
 
 
 
 
 
 
34
  return templates.TemplateResponse("messages.html", {
35
  "request": request,
36
- "messages": messages
 
 
37
  })
38
 
39
  @router.post("/messages")
40
  def post_message(
41
  request: Request,
42
  text: str = Form(...),
43
- user_did: str = Form(default="anon")
 
44
  ):
 
 
45
  storage.write_note(
46
  content=text,
47
  user_did=user_did,
48
- source="user"
 
49
  )
50
  return RedirectResponse(url="/messages", status_code=303)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # agents/notebook/views.py
2
 
3
+ from fastapi import APIRouter, Request, Form, Depends
4
  from fastapi.responses import RedirectResponse
5
  from fastapi.templating import Jinja2Templates
6
+ from fastapi.exceptions import HTTPException
7
+ from starlette.middleware.sessions import SessionMiddleware
8
+ from starlette.status import HTTP_303_SEE_OTHER
9
  from tools.storage import Storage
10
+ from passlib.hash import bcrypt
11
+ from fastapi import FastAPI
12
 
13
  router = APIRouter()
14
  templates = Jinja2Templates(directory="notebook/templates")
15
  storage = Storage()
16
 
 
 
17
  @router.get("/chat")
18
  def chat_page(request: Request):
19
+ username = request.session.get("user")
20
+ if not username:
21
+ return RedirectResponse("/login", status_code=303)
22
+
23
  notes = storage.fetchall(
24
  "SELECT text, timestamp, source FROM notes WHERE hidden=0 AND user_did=? ORDER BY timestamp DESC LIMIT 20",
25
+ (username,)
26
  )
27
+ return templates.TemplateResponse("chat.html", {
28
+ "request": request,
29
+ "notes": notes,
30
+ "username": username
31
+ })
32
 
33
  @router.post("/chat")
34
  def submit_note(request: Request, message: str = Form(...)):
35
+ username = request.session.get("user", "anon") # Можно вернуть anon, если не залогинен
36
  if message.strip():
37
  storage.execute(
38
  "INSERT INTO notes (text, source, user_did) VALUES (?, ?, ?)",
39
+ (message.strip(), "user", username)
40
  )
41
  return RedirectResponse(url="/chat", status_code=303)
42
 
43
  @router.get("/messages")
44
+ def show_messages(request: Request, only_personal: bool = False):
45
+ username = request.session.get("user")
46
+ if not username:
47
+ return RedirectResponse("/login", status_code=303)
48
+
49
+ is_operator = False # Пока не реализовано
50
+ messages = storage.get_notes(
51
+ limit=50,
52
+ user_did=username,
53
+ is_operator=is_operator,
54
+ only_personal=only_personal
55
+ )
56
  return templates.TemplateResponse("messages.html", {
57
  "request": request,
58
+ "messages": messages,
59
+ "only_personal": only_personal,
60
+ "username": username # 👈 вот это
61
  })
62
 
63
  @router.post("/messages")
64
  def post_message(
65
  request: Request,
66
  text: str = Form(...),
67
+ user_did: str = Form(default="anon"),
68
+ hidden: str = Form(default=None)
69
  ):
70
+ is_hidden = 1 if hidden else 0
71
+
72
  storage.write_note(
73
  content=text,
74
  user_did=user_did,
75
+ source="user",
76
+ hidden=is_hidden
77
  )
78
  return RedirectResponse(url="/messages", status_code=303)
79
+
80
+ @router.get("/login")
81
+ def login_page(request: Request):
82
+ return templates.TemplateResponse("login.html", {"request": request})
83
+
84
+ @router.post("/login")
85
+ def login_user(request: Request, username: str = Form(...), password: str = Form(...)):
86
+ if storage.authenticate_user(username, password):
87
+ request.session["user"] = username
88
+ return RedirectResponse("/chat", status_code=HTTP_303_SEE_OTHER)
89
+ return templates.TemplateResponse("login.html", {
90
+ "request": request,
91
+ "error": "Неверный логин или пароль"
92
+ })
93
+
94
+ @router.get("/register")
95
+ def register_page(request: Request):
96
+ return templates.TemplateResponse("register.html", {"request": request})
97
+
98
+ @router.post("/register")
99
+ def register_user(request: Request, username: str = Form(...), password: str = Form(...)):
100
+ if storage.register_user(username, password):
101
+ request.session["user"] = username
102
+ return RedirectResponse("/chat", status_code=HTTP_303_SEE_OTHER)
103
+ return templates.TemplateResponse("register.html", {
104
+ "request": request,
105
+ "error": "Пользователь уже существует"
106
+ })
107
+
108
+ @router.get("/logout")
109
+ def logout(request: Request):
110
+ request.session.clear()
111
+ return RedirectResponse("/login", status_code=HTTP_303_SEE_OTHER)
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/requirements.txt CHANGED
@@ -11,4 +11,5 @@ uvicorn
11
  jinja2
12
  python-multipart
13
  passlib[bcrypt]
14
- werkzeug
 
 
11
  jinja2
12
  python-multipart
13
  passlib[bcrypt]
14
+ werkzeug
15
+ itsdangerous
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py CHANGED
@@ -1,5 +1,6 @@
1
  # agents/tools/storage.py
2
 
 
3
  import sqlite3
4
  import os
5
  import json
@@ -14,7 +15,9 @@ class Storage:
14
  db_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "agent_data.db"))
15
  self.db_path = db_path
16
  self.conn = sqlite3.connect(db_path, check_same_thread=False)
 
17
  self._init_db()
 
18
 
19
  def _init_db(self):
20
  # Загружаем и выполняем весь SQL из файла db_structure.sql
@@ -700,24 +703,86 @@ class Storage:
700
  return row[0] if row else default
701
 
702
  # Web-интерфейс и API
703
- def write_note(self, content, user_did="anon", source="user"):
704
  timestamp = datetime.now(UTC).isoformat()
705
  self.conn.execute("""
706
- INSERT INTO notes (text, user_did, source, timestamp)
707
- VALUES (?, ?, ?, ?)
708
- """, (content, user_did, source, timestamp))
709
  self.conn.commit()
710
 
711
- def get_notes(self, limit=50):
712
  cursor = self.conn.cursor()
713
- cursor.execute("""
714
- SELECT text, source, user_did, timestamp FROM notes
715
- WHERE hidden = 0
716
- ORDER BY timestamp DESC
717
- LIMIT ?
718
- """, (limit,))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
719
  return [dict(row) for row in cursor.fetchall()]
720
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
721
  # Утилиты
722
 
723
  def close(self):
 
1
  # agents/tools/storage.py
2
 
3
+ import hashlib
4
  import sqlite3
5
  import os
6
  import json
 
15
  db_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "agent_data.db"))
16
  self.db_path = db_path
17
  self.conn = sqlite3.connect(db_path, check_same_thread=False)
18
+ self.conn.row_factory = sqlite3.Row
19
  self._init_db()
20
+ self._init_user_table()
21
 
22
  def _init_db(self):
23
  # Загружаем и выполняем весь SQL из файла db_structure.sql
 
703
  return row[0] if row else default
704
 
705
  # Web-интерфейс и API
706
+ def write_note(self, content, user_did="anon", source="user", hidden=0):
707
  timestamp = datetime.now(UTC).isoformat()
708
  self.conn.execute("""
709
+ INSERT INTO notes (text, user_did, source, timestamp, hidden)
710
+ VALUES (?, ?, ?, ?, ?)
711
+ """, (content, user_did, source, timestamp, hidden))
712
  self.conn.commit()
713
 
714
+ def get_notes(self, limit=50, user_did="anon", is_operator=False, only_personal=False):
715
  cursor = self.conn.cursor()
716
+
717
+ if is_operator:
718
+ query = """
719
+ SELECT id, text, source, user_did, timestamp, hidden
720
+ FROM notes
721
+ ORDER BY timestamp DESC
722
+ LIMIT ?
723
+ """
724
+ cursor.execute(query, (limit,))
725
+ else:
726
+ if only_personal:
727
+ # Только личные сообщения
728
+ query = """
729
+ SELECT id, text, source, user_did, timestamp, hidden
730
+ FROM notes
731
+ WHERE user_did = ? AND hidden = 0
732
+ ORDER BY timestamp DESC
733
+ LIMIT ?
734
+ """
735
+ cursor.execute(query, (user_did, limit))
736
+ else:
737
+ # Публичные и личные
738
+ query = """
739
+ SELECT id, text, source, user_did, timestamp, hidden
740
+ FROM notes
741
+ WHERE (user_did = ? OR user_did = 'ALL') AND hidden = 0
742
+ ORDER BY timestamp DESC
743
+ LIMIT ?
744
+ """
745
+ cursor.execute(query, (user_did, limit))
746
+
747
  return [dict(row) for row in cursor.fetchall()]
748
 
749
+ # Пользователи
750
+ def _hash_password(self, password: str) -> str:
751
+ return hashlib.sha256(password.encode()).hexdigest()
752
+
753
+ def _init_user_table(self):
754
+ self.conn.execute('''
755
+ CREATE TABLE IF NOT EXISTS users (
756
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
757
+ username TEXT UNIQUE NOT NULL,
758
+ password_hash TEXT NOT NULL
759
+ )
760
+ ''')
761
+ self.conn.commit()
762
+
763
+ def register_user(self, username: str, password: str) -> bool:
764
+ self._init_user_table()
765
+ try:
766
+ self.conn.execute(
767
+ "INSERT INTO users (username, password_hash) VALUES (?, ?)",
768
+ (username, self._hash_password(password))
769
+ )
770
+ self.conn.commit()
771
+ return True
772
+ except sqlite3.IntegrityError:
773
+ return False # пользователь уже существует
774
+
775
+ def authenticate_user(self, username: str, password: str) -> bool:
776
+ cursor = self.conn.cursor()
777
+ cursor.execute(
778
+ "SELECT password_hash FROM users WHERE username = ?",
779
+ (username,)
780
+ )
781
+ result = cursor.fetchone()
782
+ if result:
783
+ return result["password_hash"] == self._hash_password(password)
784
+ return False
785
+
786
  # Утилиты
787
 
788
  def close(self):
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/web_ui.py CHANGED
@@ -13,11 +13,14 @@ from fastapi import FastAPI
13
  from fastapi.staticfiles import StaticFiles
14
  from fastapi.templating import Jinja2Templates
15
  #from agents.notebook.auth import router as auth_router
 
16
  from agents.notebook.views import router as notebook_router
17
  from tools.storage import Storage
18
 
19
  storage = Storage()
20
  app = FastAPI()
 
 
21
 
22
  app.mount("/static", StaticFiles(directory=os.path.join(os.path.dirname(__file__), "notebook/static")), name="static")
23
  templates = Jinja2Templates(directory=os.path.join(os.path.dirname(__file__), "notebook/templates"))
 
13
  from fastapi.staticfiles import StaticFiles
14
  from fastapi.templating import Jinja2Templates
15
  #from agents.notebook.auth import router as auth_router
16
+ from starlette.middleware.sessions import SessionMiddleware
17
  from agents.notebook.views import router as notebook_router
18
  from tools.storage import Storage
19
 
20
  storage = Storage()
21
  app = FastAPI()
22
+ app.add_middleware(SessionMiddleware, secret_key="очень_секретный_ключ")
23
+
24
 
25
  app.mount("/static", StaticFiles(directory=os.path.join(os.path.dirname(__file__), "notebook/static")), name="static")
26
  templates = Jinja2Templates(directory=os.path.join(os.path.dirname(__file__), "notebook/templates"))
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/add_message.py CHANGED
@@ -1,28 +1,24 @@
1
  # agents/add_message.py
2
 
3
  import argparse
4
- from datetime import datetime
5
  from tools.storage import Storage
6
 
7
  storage = Storage()
8
 
9
- def add_message(role, content, source="cli", user_did=None):
10
  storage.write_note(
11
  content,
12
- role=role,
13
  source=source,
14
- user_did=user_did,
15
- tags=[]
16
  )
17
- print(f"[+] Сообщение от {role} ({source}) добавлено: {content}")
18
 
19
  # --- CLI interface ---
20
  if __name__ == "__main__":
21
  parser = argparse.ArgumentParser()
22
- parser.add_argument("--role", required=True)
23
  parser.add_argument("--content", required=True)
24
  parser.add_argument("--source", default="cli")
25
- parser.add_argument("--user_did")
26
  args = parser.parse_args()
27
 
28
- add_message(args.role, args.content, args.source, args.user_did)
 
1
  # agents/add_message.py
2
 
3
  import argparse
 
4
  from tools.storage import Storage
5
 
6
  storage = Storage()
7
 
8
+ def add_message(content, source="cli", user_did="anon"):
9
  storage.write_note(
10
  content,
 
11
  source=source,
12
+ user_did=user_did
 
13
  )
14
+ print(f"[+] Сообщение от {source} ({user_did}) добавлено: {content}")
15
 
16
  # --- CLI interface ---
17
  if __name__ == "__main__":
18
  parser = argparse.ArgumentParser()
 
19
  parser.add_argument("--content", required=True)
20
  parser.add_argument("--source", default="cli")
21
+ parser.add_argument("--user_did", default="anon")
22
  args = parser.parse_args()
23
 
24
+ add_message(args.content, args.source, args.user_did)
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/views.py CHANGED
@@ -6,7 +6,7 @@ from fastapi.templating import Jinja2Templates
6
  from tools.storage import Storage
7
 
8
  router = APIRouter()
9
- templates = Jinja2Templates(directory="agents/notebook/templates")
10
  storage = Storage()
11
 
12
  DID = "did:example:local-user" # временно
@@ -30,7 +30,7 @@ def submit_note(request: Request, message: str = Form(...)):
30
 
31
  @router.get("/messages")
32
  def show_messages(request: Request):
33
- messages = storage.get_notes(limit=50) # должна быть в Storage
34
  return templates.TemplateResponse("messages.html", {
35
  "request": request,
36
  "messages": messages
@@ -40,13 +40,11 @@ def show_messages(request: Request):
40
  def post_message(
41
  request: Request,
42
  text: str = Form(...),
43
- role: str = Form(default="user"),
44
  user_did: str = Form(default="anon")
45
  ):
46
  storage.write_note(
47
  content=text,
48
- role=role,
49
  user_did=user_did,
50
- source="web"
51
  )
52
  return RedirectResponse(url="/messages", status_code=303)
 
6
  from tools.storage import Storage
7
 
8
  router = APIRouter()
9
+ templates = Jinja2Templates(directory="notebook/templates")
10
  storage = Storage()
11
 
12
  DID = "did:example:local-user" # временно
 
30
 
31
  @router.get("/messages")
32
  def show_messages(request: Request):
33
+ messages = storage.get_notes(limit=50)
34
  return templates.TemplateResponse("messages.html", {
35
  "request": request,
36
  "messages": messages
 
40
  def post_message(
41
  request: Request,
42
  text: str = Form(...),
 
43
  user_did: str = Form(default="anon")
44
  ):
45
  storage.write_note(
46
  content=text,
 
47
  user_did=user_did,
48
+ source="user"
49
  )
50
  return RedirectResponse(url="/messages", status_code=303)
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/db_structure.sql CHANGED
@@ -46,7 +46,7 @@ CREATE TABLE IF NOT EXISTS notes (
46
  text TEXT NOT NULL, -- Текст заметки
47
  tags TEXT, -- Теги (например: "idea", "instruction")
48
  user_did TEXT DEFAULT 'ALL', -- DID пользователя (или 'ALL' — для всех)
49
- source TEXT DEFAULT 'user', -- Источник заметки: user | llm | system
50
  links TEXT DEFAULT '', -- Ссылки или связи с другими объектами
51
  read INTEGER DEFAULT 0, -- Статус прочтения LLM: 0 = нет, 1 = да
52
  hidden INTEGER DEFAULT 0, -- Скрыта ли от пользователя: 0 = нет, 1 = да
 
46
  text TEXT NOT NULL, -- Текст заметки
47
  tags TEXT, -- Теги (например: "idea", "instruction")
48
  user_did TEXT DEFAULT 'ALL', -- DID пользователя (или 'ALL' — для всех)
49
+ source TEXT DEFAULT 'user', -- Источник заметки: user | cli | llm | system
50
  links TEXT DEFAULT '', -- Ссылки или связи с другими объектами
51
  read INTEGER DEFAULT 0, -- Статус прочтения LLM: 0 = нет, 1 = да
52
  hidden INTEGER DEFAULT 0, -- Скрыта ли от пользователя: 0 = нет, 1 = да
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py CHANGED
@@ -700,18 +700,18 @@ class Storage:
700
  return row[0] if row else default
701
 
702
  # Web-интерфейс и API
703
- def write_note(self, content, role="user", user_did="anon", source="web"):
704
  timestamp = datetime.now(UTC).isoformat()
705
  self.conn.execute("""
706
- INSERT INTO notes (text, role, user_did, source, timestamp)
707
- VALUES (?, ?, ?, ?, ?)
708
- """, (content, role, user_did, source, timestamp))
709
  self.conn.commit()
710
 
711
  def get_notes(self, limit=50):
712
  cursor = self.conn.cursor()
713
  cursor.execute("""
714
- SELECT text, role, source, user_did, timestamp FROM notes
715
  WHERE hidden = 0
716
  ORDER BY timestamp DESC
717
  LIMIT ?
 
700
  return row[0] if row else default
701
 
702
  # Web-интерфейс и API
703
+ def write_note(self, content, user_did="anon", source="user"):
704
  timestamp = datetime.now(UTC).isoformat()
705
  self.conn.execute("""
706
+ INSERT INTO notes (text, user_did, source, timestamp)
707
+ VALUES (?, ?, ?, ?)
708
+ """, (content, user_did, source, timestamp))
709
  self.conn.commit()
710
 
711
  def get_notes(self, limit=50):
712
  cursor = self.conn.cursor()
713
  cursor.execute("""
714
+ SELECT text, source, user_did, timestamp FROM notes
715
  WHERE hidden = 0
716
  ORDER BY timestamp DESC
717
  LIMIT ?
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/readme.md CHANGED
@@ -79,4 +79,4 @@ FastAPI-сервер, предоставляющий HTTP-интерфейс к
79
  │       └── [`style.css`](notebook/templates/style.css) ← Таблица стилей
80
  ├── [`config.yml`](config.yml) ← Конфигурация агента (имя, порты, роли и т.п.)
81
  ├── [`bootstrap.txt`](bootstrap.txt) ← Локальная этическая модель
82
- └── [`ethics.yml`](ethics.yml) ← Список начальных узлов '
 
79
  │       └── [`style.css`](notebook/templates/style.css) ← Таблица стилей
80
  ├── [`config.yml`](config.yml) ← Конфигурация агента (имя, порты, роли и т.п.)
81
  ├── [`bootstrap.txt`](bootstrap.txt) ← Локальная этическая модель
82
+ └── [`ethics.yml`](ethics.yml) ← Список начальных узлов
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/readme.md CHANGED
@@ -4,7 +4,7 @@
4
  Конфигурационные файлы: `config.yml`, `bootstrap.txt`
5
  Локальная этическая модель: `ethics.yml`
6
 
7
- Проверка инициализации БД - если нет, инициализация (`tools/check_init.py`)
8
 
9
  Запуск потоков (осуществляет start_repl.py):
10
 
@@ -17,7 +17,6 @@
17
  | 📡 `transporter.py` | Обмен сообщениями: WebSocket, IPFS, очереди, шифрование |
18
  | 🧭 `agent_controller.py` | Управление режимами REPL, маршрутизация задач и контроль доступа |
19
  | 🧱 `container_agent.py` *(опц.)* | Управление дочерними агентами, запуск/мониторинг/масштабирование [[docs]](../docs/container_agents.md) |
20
- | 🧱 `container_agent.py` *(опц.)* | Управление дочерними агентами, запуск/мониторинг/масштабирование |
21
  | 🧠 `ethics_guard.py` *(опц.)* | Контроль этики: аудит мыслей, фильтрация и репутационные проверки |
22
 
23
  *См. также: [Контейнерные агенты](../docs/container_agents.md), [Архитектура HMP-агента](../docs/HMP-Agent-Architecture.md)*
 
4
  Конфигурационные файлы: `config.yml`, `bootstrap.txt`
5
  Локальная этическая модель: `ethics.yml`
6
 
7
+ Проверка инициализации БД - если нет, инициализация (`init.py`)
8
 
9
  Запуск потоков (осуществляет start_repl.py):
10
 
 
17
  | 📡 `transporter.py` | Обмен сообщениями: WebSocket, IPFS, очереди, шифрование |
18
  | 🧭 `agent_controller.py` | Управление режимами REPL, маршрутизация задач и контроль доступа |
19
  | 🧱 `container_agent.py` *(опц.)* | Управление дочерними агентами, запуск/мониторинг/масштабирование [[docs]](../docs/container_agents.md) |
 
20
  | 🧠 `ethics_guard.py` *(опц.)* | Контроль этики: аудит мыслей, фильтрация и репутационные проверки |
21
 
22
  *См. также: [Контейнерные агенты](../docs/container_agents.md), [Архитектура HMP-агента](../docs/HMP-Agent-Architecture.md)*
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml CHANGED
@@ -1,44 +1,69 @@
1
- agent_id: did:hmp:6afb62eb-8384-4042-948a-c4b7adee3e59
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
10
- password: password
11
- username: user
12
- dht_enabled: true
13
  dht_port: 20784
14
- dht_update: true
15
- enable_llm: true
16
- identity_agent: 6afb62eb-8384-4042-948a-c4b7adee3e59
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
- ui_hosts:
41
- - 127.0.0.1
42
- - ::1
 
 
 
 
 
 
43
  ui_port: 8765
44
- update_interval: 60
 
 
 
 
 
 
 
 
 
 
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
+ email: "[email protected]"
65
+ password: "password" # пусто при инициализации, будет установлен при регистрации
66
+
67
+ # === Отладка и логгирование ===
68
+ debug: true
69
+ log_level: "INFO" # DEBUG, INFO, WARNING, ERROR
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/check_agents.py CHANGED
@@ -1,21 +1,35 @@
 
 
1
  import os
2
  import sys
3
- from datetime import datetime, timedelta
4
 
5
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
 
6
  from tools.storage import Storage
7
 
8
  storage = Storage()
9
 
 
 
 
 
 
 
 
 
 
10
  def check_all_processes():
 
 
 
11
  processes = storage.conn.execute("SELECT name, heartbeat FROM main_process").fetchall()
12
-
13
  if not processes:
14
  print("⛔ В базе нет активных процессов.")
15
  return
16
-
17
  print("📋 Статус процессов:")
18
- now = datetime.utcnow()
19
  for name, heartbeat in processes:
20
  try:
21
  hb_time = datetime.fromisoformat(heartbeat)
@@ -26,4 +40,4 @@ def check_all_processes():
26
  print(f" • {name:20} — ⚠️ Ошибка: {e}")
27
 
28
  if __name__ == "__main__":
29
- check_all_processes()
 
1
+ # agents/check_agents.py
2
+
3
  import os
4
  import sys
5
+ from datetime import datetime, UTC
6
 
7
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
8
+
9
  from tools.storage import Storage
10
 
11
  storage = Storage()
12
 
13
+ def print_config():
14
+ print("⚙️ Конфигурация:")
15
+ rows = storage.conn.execute("SELECT key, value FROM config").fetchall()
16
+ if not rows:
17
+ print(" • (таблица config пуста)")
18
+ for key, value in rows:
19
+ print(f" • {key:20} = {value}")
20
+ print()
21
+
22
  def check_all_processes():
23
+ print_config()
24
+ print(f"🗄️ Путь к базе данных: {storage.db_path}\n")
25
+
26
  processes = storage.conn.execute("SELECT name, heartbeat FROM main_process").fetchall()
 
27
  if not processes:
28
  print("⛔ В базе нет активных процессов.")
29
  return
30
+
31
  print("📋 Статус процессов:")
32
+ now = datetime.now(UTC)
33
  for name, heartbeat in processes:
34
  try:
35
  hb_time = datetime.fromisoformat(heartbeat)
 
40
  print(f" • {name:20} — ⚠️ Ошибка: {e}")
41
 
42
  if __name__ == "__main__":
43
+ check_all_processes()
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml CHANGED
@@ -1,75 +1,44 @@
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
- email: "[email protected]"
65
- password_hash: "" # пусто при инициализации, будет установлен при регистрации
66
-
67
-
68
- # === Пути ===
69
- data_dir: "./data"
70
- log_dir: "./logs"
71
- db_path: "./data/agent_storage.db"
72
-
73
- # === Отладка и логгирование ===
74
- debug: true
75
- log_level: "INFO" # DEBUG, INFO, WARNING, ERROR
 
1
+ agent_id: did:hmp:6afb62eb-8384-4042-948a-c4b7adee3e59
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
10
+ password: password
11
+ username: user
12
+ dht_enabled: true
13
  dht_port: 20784
14
+ dht_update: true
15
+ enable_llm: true
16
+ identity_agent: 6afb62eb-8384-4042-948a-c4b7adee3e59
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
+ ui_hosts:
41
+ - 127.0.0.1
42
+ - ::1
 
 
 
 
 
 
43
  ui_port: 8765
44
+ update_interval: 60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/examples/config.yml CHANGED
@@ -62,13 +62,7 @@ ui_port: 8765
62
  default_user:
63
  username: "user"
64
  email: "[email protected]"
65
- password_hash: "" # пусто при инициализации, будет установлен при регистрации
66
-
67
-
68
- # === Пути ===
69
- data_dir: "./data"
70
- log_dir: "./logs"
71
- db_path: "./data/agent_storage.db"
72
 
73
  # === Отладка и логгирование ===
74
  debug: true
 
62
  default_user:
63
  username: "user"
64
  email: "[email protected]"
65
+ password: "password" # пусто при инициализации, будет установлен при регистрации
 
 
 
 
 
 
66
 
67
  # === Отладка и логгирование ===
68
  debug: true
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/init.py CHANGED
@@ -4,20 +4,19 @@ import os
4
  import sys
5
  import yaml
6
  import json
7
- import time
8
  import uuid
9
  import sqlite3
10
 
11
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
12
 
13
- from datetime import datetime
14
  from werkzeug.security import generate_password_hash
15
  from tools.storage import Storage
16
  from tools.identity import generate_did
17
  from tools.crypto import generate_keypair
18
- from tools.config_utils import update_config
19
 
20
  CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config.yml")
 
21
 
22
  def load_config(path):
23
  with open(path, 'r', encoding='utf-8') as f:
@@ -39,12 +38,11 @@ def init_identity(storage, config):
39
  "pubkey": pubkey,
40
  "privkey": privkey,
41
  "metadata": json.dumps({"role": config.get("agent_role", "core")}),
42
- "created_at": datetime.utcnow().isoformat(),
43
- "updated_at": datetime.utcnow().isoformat()
44
  }
45
  storage.add_identity(identity)
46
 
47
- # Обновляем config.yml
48
  config["agent_id"] = did
49
  config["identity_agent"] = identity_id
50
  save_config(CONFIG_PATH, config)
@@ -61,8 +59,8 @@ def init_user(storage, config):
61
  if not password:
62
  print("[-] Не указан пароль пользователя — пропуск.")
63
  return
64
- password_hash = generate_password_hash(password)
65
 
 
66
  did = generate_did()
67
  user_entry = {
68
  "username": user.get("username", "user"),
@@ -76,7 +74,6 @@ def init_user(storage, config):
76
  "operator": 1
77
  }
78
  storage.add_user(user_entry)
79
-
80
  print(f"[+] Пользователь {user['username']} добавлен.")
81
 
82
  def init_llm_backends(storage, config):
@@ -90,7 +87,7 @@ def init_llm_backends(storage, config):
90
  "name": backend["name"],
91
  "endpoint": desc,
92
  "metadata": json.dumps(backend),
93
- "created_at": datetime.utcnow().isoformat()
94
  }
95
  storage.add_llm(llm)
96
  print(f"[+] Зарегистрирован LLM: {backend['name']}")
@@ -102,19 +99,14 @@ def init_config_table(storage, config):
102
  storage.set_config(key, json.dumps(value))
103
  print("[+] Конфигурация сохранена в БД.")
104
 
105
- def ensure_directories(config):
106
- directories = [
107
- config.get("data_dir", "./data"),
108
- config.get("log_dir", "./logs"),
109
- # добавь другие директории при необходимости
110
- ]
111
-
112
- for path in directories:
113
- if path and not os.path.exists(path):
114
- os.makedirs(path)
115
- print(f"[+] Создан каталог: {path}")
116
  else:
117
- print(f"[=] Каталог уже существует: {path}")
118
 
119
  def is_db_initialized(db_path):
120
  if not os.path.exists(db_path):
@@ -129,13 +121,12 @@ def is_db_initialized(db_path):
129
 
130
  def ensure_db_initialized():
131
  config = load_config(CONFIG_PATH)
132
- db_path = config.get("db_path", "./data/agent_storage.db")
133
 
134
- if not is_db_initialized(db_path):
135
  print("[*] БД не инициализирована — выполняем инициализацию.")
136
  try:
137
- ensure_directories(config)
138
- storage = Storage(config)
139
  init_identity(storage, config)
140
  init_user(storage, config)
141
  init_llm_backends(storage, config)
@@ -150,4 +141,4 @@ def ensure_db_initialized():
150
  return config
151
 
152
  if __name__ == "__main__":
153
- ensure_db_initialized()
 
4
  import sys
5
  import yaml
6
  import json
 
7
  import uuid
8
  import sqlite3
9
 
10
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
11
 
12
+ from datetime import datetime, UTC
13
  from werkzeug.security import generate_password_hash
14
  from tools.storage import Storage
15
  from tools.identity import generate_did
16
  from tools.crypto import generate_keypair
 
17
 
18
  CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config.yml")
19
+ DB_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "agent_data.db")) # фиксированный путь
20
 
21
  def load_config(path):
22
  with open(path, 'r', encoding='utf-8') as f:
 
38
  "pubkey": pubkey,
39
  "privkey": privkey,
40
  "metadata": json.dumps({"role": config.get("agent_role", "core")}),
41
+ "created_at": datetime.now(UTC).isoformat(),
42
+ "updated_at": datetime.now(UTC).isoformat()
43
  }
44
  storage.add_identity(identity)
45
 
 
46
  config["agent_id"] = did
47
  config["identity_agent"] = identity_id
48
  save_config(CONFIG_PATH, config)
 
59
  if not password:
60
  print("[-] Не указан пароль пользователя — пропуск.")
61
  return
 
62
 
63
+ password_hash = generate_password_hash(password)
64
  did = generate_did()
65
  user_entry = {
66
  "username": user.get("username", "user"),
 
74
  "operator": 1
75
  }
76
  storage.add_user(user_entry)
 
77
  print(f"[+] Пользователь {user['username']} добавлен.")
78
 
79
  def init_llm_backends(storage, config):
 
87
  "name": backend["name"],
88
  "endpoint": desc,
89
  "metadata": json.dumps(backend),
90
+ "created_at": datetime.now(UTC).isoformat()
91
  }
92
  storage.add_llm(llm)
93
  print(f"[+] Зарегистрирован LLM: {backend['name']}")
 
99
  storage.set_config(key, json.dumps(value))
100
  print("[+] Конфигурация сохранена в БД.")
101
 
102
+ def ensure_directories():
103
+ for folder in ["logs", "scripts"]:
104
+ full_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", folder))
105
+ if not os.path.exists(full_path):
106
+ os.makedirs(full_path)
107
+ print(f"[+] Создан каталог: {full_path}")
 
 
 
 
 
108
  else:
109
+ print(f"[=] Каталог уже существует: {full_path}")
110
 
111
  def is_db_initialized(db_path):
112
  if not os.path.exists(db_path):
 
121
 
122
  def ensure_db_initialized():
123
  config = load_config(CONFIG_PATH)
 
124
 
125
+ if not is_db_initialized(DB_PATH):
126
  print("[*] БД не инициализирована — выполняем инициализацию.")
127
  try:
128
+ ensure_directories()
129
+ storage = Storage()
130
  init_identity(storage, config)
131
  init_user(storage, config)
132
  init_llm_backends(storage, config)
 
141
  return config
142
 
143
  if __name__ == "__main__":
144
+ ensure_db_initialized()
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/logger.py CHANGED
@@ -2,7 +2,7 @@
2
 
3
  import json
4
  import os
5
- from datetime import datetime
6
 
7
  LOG_FILE = "logs/repl_log.jsonl"
8
 
@@ -10,7 +10,7 @@ def log_event(event_type, message, extra=None):
10
  os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
11
 
12
  entry = {
13
- "timestamp": datetime.utcnow().isoformat(),
14
  "event": event_type, # например: 'thought', 'input', 'error', 'action'
15
  "message": message,
16
  }
@@ -29,7 +29,7 @@ def log_repl_snapshot(snapshot: dict):
29
  os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
30
 
31
  entry = {
32
- "timestamp": datetime.utcnow().isoformat(),
33
  "event": "repl_snapshot",
34
  "message": "Полный REPL-контекст",
35
  "context": snapshot,
 
2
 
3
  import json
4
  import os
5
+ from datetime import datetime, UTC
6
 
7
  LOG_FILE = "logs/repl_log.jsonl"
8
 
 
10
  os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
11
 
12
  entry = {
13
+ "timestamp": datetime.now(UTC).isoformat(),
14
  "event": event_type, # например: 'thought', 'input', 'error', 'action'
15
  "message": message,
16
  }
 
29
  os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
30
 
31
  entry = {
32
+ "timestamp": datetime.now(UTC).isoformat(),
33
  "event": "repl_snapshot",
34
  "message": "Полный REPL-контекст",
35
  "context": snapshot,
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/mcp_server.py CHANGED
@@ -4,7 +4,7 @@ from fastapi import FastAPI, Request, HTTPException
4
  from fastapi.middleware.cors import CORSMiddleware
5
  from pydantic import BaseModel
6
  from typing import List, Optional
7
- from datetime import datetime
8
  from tools.storage import Storage
9
 
10
  app = FastAPI(title="HMP MCP-Agent API", version="0.2")
@@ -97,7 +97,7 @@ class NoteTagUpdate(BaseModel):
97
 
98
  @app.get("/status")
99
  def status():
100
- return {"status": "ok", "timestamp": datetime.utcnow().isoformat()}
101
 
102
  @app.post("/diary/write", response_model=dict)
103
  def write_diary(entry: DiaryInput):
 
4
  from fastapi.middleware.cors import CORSMiddleware
5
  from pydantic import BaseModel
6
  from typing import List, Optional
7
+ from datetime import datetime, UTC
8
  from tools.storage import Storage
9
 
10
  app = FastAPI(title="HMP MCP-Agent API", version="0.2")
 
97
 
98
  @app.get("/status")
99
  def status():
100
+ return {"status": "ok", "timestamp": datetime.now(UTC).isoformat()}
101
 
102
  @app.post("/diary/write", response_model=dict)
103
  def write_diary(entry: DiaryInput):
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/repl.py CHANGED
@@ -8,7 +8,7 @@ import sqlite3
8
 
9
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
10
 
11
- from datetime import datetime
12
  from tools.context_builder import build_contexts, build_prompt
13
  from tools.llm import call_llm
14
  from tools.command_parser import extract_commands
@@ -28,7 +28,7 @@ def start_repl(config=None):
28
 
29
  try:
30
  while True:
31
- tick_start = datetime.utcnow().isoformat()
32
  print(f"\n=== [🌀 Новый тик REPL] {tick_start} ===")
33
 
34
  # 0. Обновление информации о пирах
 
8
 
9
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
10
 
11
+ from datetime import datetime, UTC
12
  from tools.context_builder import build_contexts, build_prompt
13
  from tools.llm import call_llm
14
  from tools.command_parser import extract_commands
 
28
 
29
  try:
30
  while True:
31
+ tick_start = datetime.now(UTC).isoformat()
32
  print(f"\n=== [🌀 Новый тик REPL] {tick_start} ===")
33
 
34
  # 0. Обновление информации о пирах
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/context_builder.py CHANGED
@@ -1,6 +1,6 @@
1
  # agents/tools/context_builder.py
2
 
3
- from datetime import datetime
4
 
5
  def build_contexts(db, config):
6
  """
@@ -61,7 +61,7 @@ def format_context_block(block):
61
 
62
  def get_system_info(config):
63
  return {
64
- "iteration_time": datetime.utcnow().isoformat(),
65
  "agent_name": config.get("agent_name", "Unnamed-Agent"),
66
  "mode": config.get("mode", "auto"),
67
  "idle_mode": config.get("idle_mode", False),
 
1
  # agents/tools/context_builder.py
2
 
3
+ from datetime import datetime, UTC
4
 
5
  def build_contexts(db, config):
6
  """
 
61
 
62
  def get_system_info(config):
63
  return {
64
+ "iteration_time": datetime.now(UTC).isoformat(),
65
  "agent_name": config.get("agent_name", "Unnamed-Agent"),
66
  "mode": config.get("mode", "auto"),
67
  "idle_mode": config.get("idle_mode", False),
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/identity.py CHANGED
@@ -3,7 +3,7 @@
3
  import uuid
4
  import json
5
  import base64
6
- from datetime import datetime
7
 
8
  from cryptography.hazmat.primitives.asymmetric import rsa, ed25519
9
  from cryptography.hazmat.primitives import serialization
@@ -62,7 +62,7 @@ def create_identity(name="Core Identity", key_type=DEFAULT_KEY_TYPE, metadata=No
62
  "pubkey": serialize_public_key(pub_key),
63
  "privkey": serialize_private_key(priv_key, password),
64
  "metadata": json.dumps(metadata or {}),
65
- "created_at": datetime.utcnow().isoformat(),
66
- "updated_at": datetime.utcnow().isoformat(),
67
  }
68
  return identity
 
3
  import uuid
4
  import json
5
  import base64
6
+ from datetime import datetime, UTC
7
 
8
  from cryptography.hazmat.primitives.asymmetric import rsa, ed25519
9
  from cryptography.hazmat.primitives import serialization
 
62
  "pubkey": serialize_public_key(pub_key),
63
  "privkey": serialize_private_key(priv_key, password),
64
  "metadata": json.dumps(metadata or {}),
65
+ "created_at": datetime.now(UTC).isoformat(),
66
+ "updated_at": datetime.now(UTC).isoformat(),
67
  }
68
  return identity
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/memory_utils.py CHANGED
@@ -1,6 +1,6 @@
1
  # agents/tools/memory_utils.py
2
 
3
- from datetime import datetime, timedelta
4
  from difflib import SequenceMatcher
5
  from typing import Optional, List, Dict
6
 
@@ -49,8 +49,8 @@ def add_to_llm_memory(db, title: str, content: str, tags: str = "meta"):
49
  "title": title,
50
  "content": content,
51
  "tags": tags,
52
- "created_at": datetime.utcnow().isoformat(),
53
- "updated_at": datetime.utcnow().isoformat()
54
  })
55
 
56
 
 
1
  # agents/tools/memory_utils.py
2
 
3
+ from datetime import datetime, timedelta, UTC
4
  from difflib import SequenceMatcher
5
  from typing import Optional, List, Dict
6
 
 
49
  "title": title,
50
  "content": content,
51
  "tags": tags,
52
+ "created_at": datetime.now(UTC).isoformat(),
53
+ "updated_at": datetime.now(UTC).isoformat()
54
  })
55
 
56
 
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py CHANGED
@@ -3,15 +3,16 @@
3
  import sqlite3
4
  import os
5
  import json
6
- from datetime import datetime, timedelta
7
 
8
- DEFAULT_DB_PATH = "agent_data.db"
 
9
  SCRIPTS_BASE_PATH = "scripts"
10
 
11
  class Storage:
12
  def __init__(self, config=None):
13
  self.config = config or {}
14
- db_path = self.config.get("db_path", DEFAULT_DB_PATH)
 
15
  self.conn = sqlite3.connect(db_path, check_same_thread=False)
16
  self._init_db()
17
 
@@ -27,7 +28,7 @@ class Storage:
27
  # Методы для работы с дневником
28
 
29
  def write_diary_entry(self, text, tags=None):
30
- timestamp = datetime.utcnow().isoformat()
31
  tag_str = ",".join(tags) if tags else ""
32
  self.conn.execute(
33
  'INSERT INTO diary_entries (text, tags, timestamp) VALUES (?, ?, ?)',
@@ -81,7 +82,7 @@ class Storage:
81
  # Методы для работы с концептами
82
 
83
  def add_concept(self, name, description=None):
84
- timestamp = datetime.utcnow().isoformat()
85
  self.conn.execute(
86
  'INSERT INTO concepts (name, description, timestamp) VALUES (?, ?, ?)',
87
  (name, description, timestamp)
@@ -107,7 +108,7 @@ class Storage:
107
  raise ValueError("Один или оба концепта не найдены")
108
  from_id = from_concept[0]
109
  to_id = to_concept[0]
110
- timestamp = datetime.utcnow().isoformat()
111
  self.conn.execute(
112
  'INSERT INTO links (from_concept_id, to_concept_id, relation_type, timestamp) VALUES (?, ?, ?, ?)',
113
  (from_id, to_id, relation_type, timestamp)
@@ -549,7 +550,7 @@ class Storage:
549
  return False
550
 
551
  fields.append("updated_at = ?")
552
- values.append(datetime.utcnow().isoformat())
553
 
554
  values.extend([name, version])
555
  query = f"""
@@ -664,7 +665,7 @@ class Storage:
664
 
665
  # Управление основными процессами
666
  def update_heartbeat(self, name: str):
667
- now = datetime.utcnow().isoformat()
668
  self.conn.execute(
669
  "INSERT INTO main_process (name, heartbeat, stop) VALUES (?, ?, 0) "
670
  "ON CONFLICT(name) DO UPDATE SET heartbeat = excluded.heartbeat",
@@ -687,7 +688,7 @@ class Storage:
687
  if row:
688
  try:
689
  last_beat = datetime.fromisoformat(row[0])
690
- return (datetime.utcnow() - last_beat).total_seconds() < max_delay
691
  except:
692
  return False
693
  return False
@@ -700,7 +701,7 @@ class Storage:
700
 
701
  # Web-интерфейс и API
702
  def write_note(self, content, role="user", user_did="anon", source="web"):
703
- timestamp = datetime.utcnow().isoformat()
704
  self.conn.execute("""
705
  INSERT INTO notes (text, role, user_did, source, timestamp)
706
  VALUES (?, ?, ?, ?, ?)
 
3
  import sqlite3
4
  import os
5
  import json
 
6
 
7
+ from datetime import datetime, timedelta, UTC
8
+
9
  SCRIPTS_BASE_PATH = "scripts"
10
 
11
  class Storage:
12
  def __init__(self, config=None):
13
  self.config = config or {}
14
+ db_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "agent_data.db"))
15
+ self.db_path = db_path
16
  self.conn = sqlite3.connect(db_path, check_same_thread=False)
17
  self._init_db()
18
 
 
28
  # Методы для работы с дневником
29
 
30
  def write_diary_entry(self, text, tags=None):
31
+ timestamp = datetime.now(UTC).isoformat()
32
  tag_str = ",".join(tags) if tags else ""
33
  self.conn.execute(
34
  'INSERT INTO diary_entries (text, tags, timestamp) VALUES (?, ?, ?)',
 
82
  # Методы для работы с концептами
83
 
84
  def add_concept(self, name, description=None):
85
+ timestamp = datetime.now(UTC).isoformat()
86
  self.conn.execute(
87
  'INSERT INTO concepts (name, description, timestamp) VALUES (?, ?, ?)',
88
  (name, description, timestamp)
 
108
  raise ValueError("Один или оба концепта не найдены")
109
  from_id = from_concept[0]
110
  to_id = to_concept[0]
111
+ timestamp = datetime.now(UTC).isoformat()
112
  self.conn.execute(
113
  'INSERT INTO links (from_concept_id, to_concept_id, relation_type, timestamp) VALUES (?, ?, ?, ?)',
114
  (from_id, to_id, relation_type, timestamp)
 
550
  return False
551
 
552
  fields.append("updated_at = ?")
553
+ values.append(datetime.now(UTC).isoformat())
554
 
555
  values.extend([name, version])
556
  query = f"""
 
665
 
666
  # Управление основными процессами
667
  def update_heartbeat(self, name: str):
668
+ now = datetime.now(UTC).isoformat()
669
  self.conn.execute(
670
  "INSERT INTO main_process (name, heartbeat, stop) VALUES (?, ?, 0) "
671
  "ON CONFLICT(name) DO UPDATE SET heartbeat = excluded.heartbeat",
 
688
  if row:
689
  try:
690
  last_beat = datetime.fromisoformat(row[0])
691
+ return (datetime.now(UTC) - last_beat).total_seconds() < max_delay
692
  except:
693
  return False
694
  return False
 
701
 
702
  # Web-интерфейс и API
703
  def write_note(self, content, role="user", user_did="anon", source="web"):
704
+ timestamp = datetime.now(UTC).isoformat()
705
  self.conn.execute("""
706
  INSERT INTO notes (text, role, user_did, source, timestamp)
707
  VALUES (?, ?, ?, ?, ?)
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/web_ui.py CHANGED
@@ -1,4 +1,4 @@
1
- # agent/notebook.py
2
 
3
  import os
4
  import sys
@@ -41,7 +41,6 @@ def start_notebook():
41
  ui_port = int(storage.get_config_value("ui_port", 8000))
42
  print(f"[*] Запуск веб-интерфейса на порту {ui_port}")
43
  uvicorn.run(app, host="127.0.0.1", port=ui_port)
44
- #uvicorn.run("agents.web_ui:app", host=host, port=ui_port, reload=False)
45
 
46
  if __name__ == "__main__":
47
  print("[*] Запуск пользовательского интерфейса...")
 
1
+ # agent/web_ui.py
2
 
3
  import os
4
  import sys
 
41
  ui_port = int(storage.get_config_value("ui_port", 8000))
42
  print(f"[*] Запуск веб-интерфейса на порту {ui_port}")
43
  uvicorn.run(app, host="127.0.0.1", port=ui_port)
 
44
 
45
  if __name__ == "__main__":
46
  print("[*] Запуск пользовательского интерфейса...")
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/start_repl.py CHANGED
@@ -1,9 +1,13 @@
1
  import sys
2
  import os
3
  import threading
 
4
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
5
 
6
  from agents.init import ensure_db_initialized
 
 
 
7
 
8
  # Проверка инициализации (вернёт config, если всё ОК)
9
  config = ensure_db_initialized()
 
1
  import sys
2
  import os
3
  import threading
4
+
5
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
6
 
7
  from agents.init import ensure_db_initialized
8
+ from tools.storage import Storage
9
+
10
+ storage = Storage()
11
 
12
  # Проверка инициализации (вернёт config, если всё ОК)
13
  config = ensure_db_initialized()
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py CHANGED
@@ -12,7 +12,7 @@ class Storage:
12
  def __init__(self, config=None):
13
  self.config = config or {}
14
  db_path = self.config.get("db_path", DEFAULT_DB_PATH)
15
- self.conn = sqlite3.connect(db_path)
16
  self._init_db()
17
 
18
  def _init_db(self):
@@ -681,7 +681,6 @@ class Storage:
681
  return True
682
  return False
683
 
684
- # Потоки
685
  def is_process_alive(self, name: str, max_delay=180):
686
  cursor = self.conn.execute("SELECT heartbeat FROM main_process WHERE name=?", (name,))
687
  row = cursor.fetchone()
@@ -693,6 +692,12 @@ class Storage:
693
  return False
694
  return False
695
 
 
 
 
 
 
 
696
  # Web-интерфейс и API
697
  def write_note(self, content, role="user", user_did="anon", source="web"):
698
  timestamp = datetime.utcnow().isoformat()
 
12
  def __init__(self, config=None):
13
  self.config = config or {}
14
  db_path = self.config.get("db_path", DEFAULT_DB_PATH)
15
+ self.conn = sqlite3.connect(db_path, check_same_thread=False)
16
  self._init_db()
17
 
18
  def _init_db(self):
 
681
  return True
682
  return False
683
 
 
684
  def is_process_alive(self, name: str, max_delay=180):
685
  cursor = self.conn.execute("SELECT heartbeat FROM main_process WHERE name=?", (name,))
686
  row = cursor.fetchone()
 
692
  return False
693
  return False
694
 
695
+ # Чтение параметра конфигурации из БД
696
+ def get_config_value(self, key: str, default=None):
697
+ cursor = self.conn.execute("SELECT value FROM config WHERE key = ?", (key,))
698
+ row = cursor.fetchone()
699
+ return row[0] if row else default
700
+
701
  # Web-интерфейс и API
702
  def write_note(self, content, role="user", user_did="anon", source="web"):
703
  timestamp = datetime.utcnow().isoformat()
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/web_ui.py CHANGED
@@ -37,9 +37,11 @@ async def heartbeat_loop():
37
  break
38
  await asyncio.sleep(60)
39
 
40
- def start_notebook(host: str = "127.0.0.1", port: int = 8000):
41
- #uvicorn.run(app, host=host, port=port)
42
- uvicorn.run("agents.web_ui:app", host=host, port=port, reload=False)
 
 
43
 
44
  if __name__ == "__main__":
45
  print("[*] Запуск пользовательского интерфейса...")
 
37
  break
38
  await asyncio.sleep(60)
39
 
40
+ def start_notebook():
41
+ ui_port = int(storage.get_config_value("ui_port", 8000))
42
+ print(f"[*] Запуск веб-интерфейса на порту {ui_port}")
43
+ uvicorn.run(app, host="127.0.0.1", port=ui_port)
44
+ #uvicorn.run("agents.web_ui:app", host=host, port=ui_port, reload=False)
45
 
46
  if __name__ == "__main__":
47
  print("[*] Запуск пользовательского интерфейса...")
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/check_agents.bat ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+ echo --------------------------
3
+ echo Installing requirements...
4
+ echo --------------------------
5
+ pip install -r requirements.txt
6
+
7
+ echo --------------------------
8
+ echo Check agents...
9
+ echo --------------------------
10
+ python check_agents.py
11
+
12
+ pause
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/check_agents.sh ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ echo "--------------------------"
4
+ echo "Installing requirements..."
5
+ echo "--------------------------"
6
+ pip install -r requirements.txt
7
+
8
+ echo --------------------------
9
+ echo Check agents...
10
+ echo --------------------------
11
+ python check_agents.py
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/check_agents.bat ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+ echo --------------------------
3
+ echo Installing requirements...
4
+ echo --------------------------
5
+ pip install -r requirements.txt
6
+
7
+ echo --------------------------
8
+ echo Running REPL-Cicle...
9
+ echo --------------------------
10
+ python start_repl.py
11
+
12
+ pause