GitHub Action
commited on
Commit
·
75191db
1
Parent(s):
e78479b
Sync from GitHub with Git LFS
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- agents/add_message.py +5 -3
- agents/tools/storage.py +1 -1
- hf_repo/agents/notebook/views.py +11 -3
- hf_repo/agents/tools/__init__.py +1 -1
- hf_repo/hf_repo/agents/notebook/templates/messages.html +2 -2
- hf_repo/hf_repo/hf_repo/agents/notebook/views.py +1 -1
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/views.py +11 -1
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/requirements.txt +2 -1
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html +2 -2
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py +1 -1
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html +1 -1
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/db_structure.sql +4 -3
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/views.py +5 -1
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py +12 -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/agents/notebook/templates/messages.html +3 -3
- 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/notebook/templates/messages.html +4 -3
- 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/notebook/templates/messages.html +2 -2
- 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/notebook/templates/messages.html +2 -2
- 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/notebook/templates/messages.html +1 -1
- 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/hf_repo/agents/notebook/views.py +0 -5
- 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/hf_repo/hf_repo/agents/tools/storage.py +35 -26
- 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/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/views.py +15 -9
- 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/hf_repo/hf_repo/hf_repo/hf_repo/agents/web_ui.py +0 -2
- 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/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/login.html +14 -6
- 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/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html +2 -4
- 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/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/register.html +15 -7
- 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/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py +7 -7
- 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/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml +65 -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/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/notebook/templates/login.html +1 -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/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/notebook/templates/register.html +1 -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/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 -65
- 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/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/login.html +5 -14
- 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/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html +9 -2
- 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/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/register.html +6 -14
- 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/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/views.py +36 -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/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 +26 -19
- 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/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/notebook/templates/login.html +14 -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/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/notebook/templates/messages.html +40 -8
- 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/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/notebook/templates/register.html +14 -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/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/notebook/views.py +72 -11
- 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/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/requirements.txt +2 -1
- 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/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 +76 -11
- 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/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 +3 -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/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/add_message.py +5 -9
- 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/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/notebook/views.py +3 -5
- 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/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/db_structure.sql +1 -1
- 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/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 +5 -5
- 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/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/readme.md +1 -1
- 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/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/config.yml +65 -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/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/hf_repo/agents/readme.md +1 -2
agents/add_message.py
CHANGED
@@ -5,11 +5,12 @@ 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 |
|
@@ -19,6 +20,7 @@ if __name__ == "__main__":
|
|
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)
|
|
|
5 |
|
6 |
storage = Storage()
|
7 |
|
8 |
+
def add_message(content, source="cli", user_did="anon", hidden=1):
|
9 |
storage.write_note(
|
10 |
content,
|
11 |
source=source,
|
12 |
+
user_did=user_did,
|
13 |
+
hidden=hidden
|
14 |
)
|
15 |
print(f"[+] Сообщение от {source} ({user_did}) добавлено: {content}")
|
16 |
|
|
|
20 |
parser.add_argument("--content", required=True)
|
21 |
parser.add_argument("--source", default="cli")
|
22 |
parser.add_argument("--user_did", default="anon")
|
23 |
+
parser.add_argument("--hidden", default=1)
|
24 |
args = parser.parse_args()
|
25 |
|
26 |
+
add_message(args.content, args.source, args.user_did, args.hidden)
|
agents/tools/storage.py
CHANGED
@@ -735,7 +735,7 @@ class Storage:
|
|
735 |
FROM notes n
|
736 |
LEFT JOIN users u ON n.user_did = u.did
|
737 |
WHERE n.user_did = ?
|
738 |
-
OR ((n.source = 'user' OR n.source = 'llm') AND n.hidden = 0)
|
739 |
ORDER BY n.timestamp DESC
|
740 |
LIMIT ?
|
741 |
"""
|
|
|
735 |
FROM notes n
|
736 |
LEFT JOIN users u ON n.user_did = u.did
|
737 |
WHERE n.user_did = ?
|
738 |
+
OR ((n.source = 'user' OR n.source = 'llm' OR n.source = 'cli') AND n.hidden = 0)
|
739 |
ORDER BY n.timestamp DESC
|
740 |
LIMIT ?
|
741 |
"""
|
hf_repo/agents/notebook/views.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
# agents/notebook/views.py
|
2 |
|
|
|
3 |
import bleach
|
4 |
|
5 |
from fastapi import APIRouter, Request, Form
|
@@ -12,13 +13,20 @@ router = APIRouter()
|
|
12 |
templates = Jinja2Templates(directory="notebook/templates")
|
13 |
storage = Storage()
|
14 |
|
15 |
-
allowed_tags = ['b', 'i', 's', 'u', 'a', 'ol', 'ul', 'li', 'dl', 'dt', 'dd', 'table', 'caption', 'tr', 'th', 'td']
|
16 |
allowed_attributes = {
|
17 |
'a': ['href', 'title']
|
18 |
}
|
19 |
|
20 |
-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
@router.get("/chat")
|
24 |
def chat_page(request: Request):
|
|
|
1 |
# agents/notebook/views.py
|
2 |
|
3 |
+
import re
|
4 |
import bleach
|
5 |
|
6 |
from fastapi import APIRouter, Request, Form
|
|
|
13 |
templates = Jinja2Templates(directory="notebook/templates")
|
14 |
storage = Storage()
|
15 |
|
16 |
+
allowed_tags = ['b', 'i', 's', 'u', 'a', 'ol', 'ul', 'li', 'dl', 'dt', 'dd', 'table', 'caption', 'tr', 'th', 'td', 'code', 'pre', 'blockquote', 'br', 'hr']
|
17 |
allowed_attributes = {
|
18 |
'a': ['href', 'title']
|
19 |
}
|
20 |
|
21 |
+
# Очистка сообщений
|
22 |
+
def sanitize_html(text: str) -> str:
|
23 |
+
# 1. Сначала очищаем HTML
|
24 |
+
cleaned = bleach.clean(text, tags=allowed_tags, attributes=allowed_attributes, strip=True)
|
25 |
+
|
26 |
+
# 2. Заменяем 3 и более <br> подряд на ровно два
|
27 |
+
cleaned = re.sub(r'(<br\s*/?>\s*){3,}', '<br><br>', cleaned, flags=re.IGNORECASE)
|
28 |
+
|
29 |
+
return cleaned
|
30 |
|
31 |
@router.get("/chat")
|
32 |
def chat_page(request: Request):
|
hf_repo/agents/tools/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1 |
-
from
|
|
|
1 |
+
from tools.storage import Storage
|
hf_repo/hf_repo/agents/notebook/templates/messages.html
CHANGED
@@ -25,8 +25,8 @@
|
|
25 |
|
26 |
<form method="post">
|
27 |
<textarea name="text" rows="3" cols="40" placeholder="Введите сообщение..."></textarea><br>
|
28 |
-
<button name="hidden" value="false" type="submit"
|
29 |
-
<button name="hidden" value="true" type="submit"
|
30 |
</form>
|
31 |
|
32 |
<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>
|
hf_repo/hf_repo/hf_repo/agents/notebook/views.py
CHANGED
@@ -12,7 +12,7 @@ router = APIRouter()
|
|
12 |
templates = Jinja2Templates(directory="notebook/templates")
|
13 |
storage = Storage()
|
14 |
|
15 |
-
allowed_tags = ['b', 'i', 'a', 'ol', 'ul', 'li', 'dl', 'dt', 'dd', 'table', 'caption', 'tr', 'th', 'td']
|
16 |
allowed_attributes = {
|
17 |
'a': ['href', 'title']
|
18 |
}
|
|
|
12 |
templates = Jinja2Templates(directory="notebook/templates")
|
13 |
storage = Storage()
|
14 |
|
15 |
+
allowed_tags = ['b', 'i', 's', 'u', 'a', 'ol', 'ul', 'li', 'dl', 'dt', 'dd', 'table', 'caption', 'tr', 'th', 'td']
|
16 |
allowed_attributes = {
|
17 |
'a': ['href', 'title']
|
18 |
}
|
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/views.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
# agents/notebook/views.py
|
2 |
|
|
|
|
|
3 |
from fastapi import APIRouter, Request, Form
|
4 |
from fastapi.responses import RedirectResponse, HTMLResponse
|
5 |
from fastapi.templating import Jinja2Templates
|
@@ -10,6 +12,14 @@ router = APIRouter()
|
|
10 |
templates = Jinja2Templates(directory="notebook/templates")
|
11 |
storage = Storage()
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
@router.get("/chat")
|
14 |
def chat_page(request: Request):
|
15 |
did = request.session.get("did")
|
@@ -72,7 +82,7 @@ def post_message(
|
|
72 |
|
73 |
if text.strip():
|
74 |
storage.write_note(
|
75 |
-
content=text.strip(),
|
76 |
user_did=did,
|
77 |
source="user",
|
78 |
hidden=is_hidden
|
|
|
1 |
# agents/notebook/views.py
|
2 |
|
3 |
+
import bleach
|
4 |
+
|
5 |
from fastapi import APIRouter, Request, Form
|
6 |
from fastapi.responses import RedirectResponse, HTMLResponse
|
7 |
from fastapi.templating import Jinja2Templates
|
|
|
12 |
templates = Jinja2Templates(directory="notebook/templates")
|
13 |
storage = Storage()
|
14 |
|
15 |
+
allowed_tags = ['b', 'i', 'a', 'ol', 'ul', 'li', 'dl', 'dt', 'dd', 'table', 'caption', 'tr', 'th', 'td']
|
16 |
+
allowed_attributes = {
|
17 |
+
'a': ['href', 'title']
|
18 |
+
}
|
19 |
+
|
20 |
+
def sanitize_html(text):
|
21 |
+
return bleach.clean(text, tags=allowed_tags, attributes=allowed_attributes, strip=True)
|
22 |
+
|
23 |
@router.get("/chat")
|
24 |
def chat_page(request: Request):
|
25 |
did = request.session.get("did")
|
|
|
82 |
|
83 |
if text.strip():
|
84 |
storage.write_note(
|
85 |
+
content=sanitize_html(text.strip()),
|
86 |
user_did=did,
|
87 |
source="user",
|
88 |
hidden=is_hidden
|
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/requirements.txt
CHANGED
@@ -12,4 +12,5 @@ jinja2
|
|
12 |
python-multipart
|
13 |
passlib[bcrypt]
|
14 |
werkzeug
|
15 |
-
itsdangerous
|
|
|
|
12 |
python-multipart
|
13 |
passlib[bcrypt]
|
14 |
werkzeug
|
15 |
+
itsdangerous
|
16 |
+
bleach
|
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html
CHANGED
@@ -46,10 +46,10 @@
|
|
46 |
Источник: <i>{{ msg.source }}</i> — {{ msg.timestamp[:19].replace('T', ' ') }}
|
47 |
</div>
|
48 |
<div>
|
49 |
-
{{ msg.badges }}Пользователь: {% if msg.username %}<b>{{ msg.username }}</b>{% endif %} {% if msg.user_did
|
50 |
</div>
|
51 |
<hr>
|
52 |
-
<div>{{ msg.text }}</div>
|
53 |
</div>
|
54 |
{% endfor %}
|
55 |
</body>
|
|
|
46 |
Источник: <i>{{ msg.source }}</i> — {{ msg.timestamp[:19].replace('T', ' ') }}
|
47 |
</div>
|
48 |
<div>
|
49 |
+
{% if msg.badges %}{{ msg.badges }}{% endif %}Пользователь: {% if msg.username %}<b>{{ msg.username }}</b>{% endif %} {% if msg.user_did %}({{ msg.user_did }}){% endif %}
|
50 |
</div>
|
51 |
<hr>
|
52 |
+
<div>{{ msg.text|safe }}</div>
|
53 |
</div>
|
54 |
{% endfor %}
|
55 |
</body>
|
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/storage.py
CHANGED
@@ -731,7 +731,7 @@ class Storage:
|
|
731 |
else:
|
732 |
# Личные сообщения + публичные от user/llm, которые не скрыты
|
733 |
query = """
|
734 |
-
SELECT n.id, n.text, n.source, n.user_did, u.username, n.timestamp, n.hidden
|
735 |
FROM notes n
|
736 |
LEFT JOIN users u ON n.user_did = u.did
|
737 |
WHERE n.user_did = ?
|
|
|
731 |
else:
|
732 |
# Личные сообщения + публичные от user/llm, которые не скрыты
|
733 |
query = """
|
734 |
+
SELECT n.id, n.text, n.source, n.user_did, u.username, u.badges, n.timestamp, n.hidden
|
735 |
FROM notes n
|
736 |
LEFT JOIN users u ON n.user_did = u.did
|
737 |
WHERE n.user_did = ?
|
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/messages.html
CHANGED
@@ -46,7 +46,7 @@
|
|
46 |
Источник: <i>{{ msg.source }}</i> — {{ msg.timestamp[:19].replace('T', ' ') }}
|
47 |
</div>
|
48 |
<div>
|
49 |
-
Пользователь: {% if msg.username %}<b>{{ msg.username }}</b>{% endif %} {% if msg.user_did !="" %}({{ msg.user_did }}){% endif %}
|
50 |
</div>
|
51 |
<hr>
|
52 |
<div>{{ msg.text }}</div>
|
|
|
46 |
Источник: <i>{{ msg.source }}</i> — {{ msg.timestamp[:19].replace('T', ' ') }}
|
47 |
</div>
|
48 |
<div>
|
49 |
+
{{ msg.badges }}Пользователь: {% if msg.username %}<b>{{ msg.username }}</b>{% endif %} {% if msg.user_did !="" %}({{ msg.user_did }}){% endif %}
|
50 |
</div>
|
51 |
<hr>
|
52 |
<div>{{ msg.text }}</div>
|
hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/db_structure.sql
CHANGED
@@ -199,9 +199,10 @@ CREATE TABLE IF NOT EXISTS users (
|
|
199 |
user_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
200 |
ban DATETIME DEFAULT NULL, -- если стоит дата/время, то пользователь забанен до этого момента
|
201 |
username TEXT, -- имя пользователя (необязательно уникальное)
|
202 |
-
|
203 |
-
|
204 |
-
|
|
|
205 |
info TEXT, -- произвольная информация, JSON
|
206 |
profile TEXT, -- структурированая информация, JSON
|
207 |
contacts TEXT, -- JSON-массив альтернативных контактов (matrix, telegram и т.д.)
|
|
|
199 |
user_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
200 |
ban DATETIME DEFAULT NULL, -- если стоит дата/время, то пользователь забанен до этого момента
|
201 |
username TEXT, -- имя пользователя (необязательно уникальное)
|
202 |
+
badges TEXT, -- значки, присвоенные агентом (например, "🎓💬")
|
203 |
+
did TEXT UNIQUE NOT NULL, -- децентрализованный идентификатор
|
204 |
+
mail TEXT UNIQUE NOT NULL, -- электронная почта
|
205 |
+
password_hash TEXT NOT NULL, -- хэш пароля
|
206 |
info TEXT, -- произвольная информация, JSON
|
207 |
profile TEXT, -- структурированая информация, JSON
|
208 |
contacts TEXT, -- JSON-массив альтернативных контактов (matrix, telegram и т.д.)
|
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
@@ -1,7 +1,7 @@
|
|
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 starlette.status import HTTP_303_SEE_OTHER
|
7 |
from tools.storage import Storage
|
@@ -66,6 +66,10 @@ def post_message(
|
|
66 |
did = request.session.get("did", "anon")
|
67 |
is_hidden = 1 if hidden.lower() == "true" else 0
|
68 |
|
|
|
|
|
|
|
|
|
69 |
if text.strip():
|
70 |
storage.write_note(
|
71 |
content=text.strip(),
|
|
|
1 |
# agents/notebook/views.py
|
2 |
|
3 |
from fastapi import APIRouter, Request, Form
|
4 |
+
from fastapi.responses import RedirectResponse, HTMLResponse
|
5 |
from fastapi.templating import Jinja2Templates
|
6 |
from starlette.status import HTTP_303_SEE_OTHER
|
7 |
from tools.storage import Storage
|
|
|
66 |
did = request.session.get("did", "anon")
|
67 |
is_hidden = 1 if hidden.lower() == "true" else 0
|
68 |
|
69 |
+
# Проверка на бан
|
70 |
+
if storage.is_banned(did):
|
71 |
+
return HTMLResponse(content="Вы забанены и не можете отправлять сообщения.", status_code=403)
|
72 |
+
|
73 |
if text.strip():
|
74 |
storage.write_note(
|
75 |
content=text.strip(),
|
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
@@ -769,6 +769,18 @@ class Storage:
|
|
769 |
return check_password_hash(result["password_hash"], password)
|
770 |
return False
|
771 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
772 |
def get_user_info(self, mail: str) -> dict | None:
|
773 |
mail = mail.lower()
|
774 |
cursor = self.conn.cursor()
|
|
|
769 |
return check_password_hash(result["password_hash"], password)
|
770 |
return False
|
771 |
|
772 |
+
def is_banned(self, user_did):
|
773 |
+
result = self.conn.execute("""
|
774 |
+
SELECT ban
|
775 |
+
FROM users
|
776 |
+
WHERE did = ?
|
777 |
+
""", (user_did,)).fetchone()
|
778 |
+
|
779 |
+
if result and result["ban"]:
|
780 |
+
return datetime.fromisoformat(result["ban"]) > datetime.now(UTC)
|
781 |
+
|
782 |
+
return False
|
783 |
+
|
784 |
def get_user_info(self, mail: str) -> dict | None:
|
785 |
mail = mail.lower()
|
786 |
cursor = self.conn.cursor()
|
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/notebook/templates/messages.html
CHANGED
@@ -33,7 +33,7 @@
|
|
33 |
|
34 |
<div>
|
35 |
<a href="/messages">📢 Все сообщения</a> |
|
36 |
-
<a href="/messages?only_personal=true">🙋
|
37 |
</div>
|
38 |
|
39 |
<hr>
|
@@ -41,8 +41,8 @@
|
|
41 |
{% for msg in messages %}
|
42 |
<div class="message source-{{ msg.source }}">
|
43 |
<div>
|
44 |
-
{% if msg.user_did == request.session['did'] %}<span class="from-self"></span>{% endif %}
|
45 |
-
{% if msg.hidden %}<span class="private"></span>{% endif %}
|
46 |
Источник: <i>{{ msg.source }}</i> — {{ msg.timestamp[:19].replace('T', ' ') }}
|
47 |
</div>
|
48 |
<div>
|
|
|
33 |
|
34 |
<div>
|
35 |
<a href="/messages">📢 Все сообщения</a> |
|
36 |
+
<a href="/messages?only_personal=true">🙋 Личные</a>
|
37 |
</div>
|
38 |
|
39 |
<hr>
|
|
|
41 |
{% for msg in messages %}
|
42 |
<div class="message source-{{ msg.source }}">
|
43 |
<div>
|
44 |
+
{% if msg.user_did == request.session['did'] %}<span class="from-self" title="это ваше сообщение"></span>{% endif %}
|
45 |
+
{% if msg.hidden %}<span class="private" title="личное сообщение"></span>{% endif %}
|
46 |
Источник: <i>{{ msg.source }}</i> — {{ msg.timestamp[:19].replace('T', ' ') }}
|
47 |
</div>
|
48 |
<div>
|
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/notebook/templates/messages.html
CHANGED
@@ -39,13 +39,14 @@
|
|
39 |
<hr>
|
40 |
|
41 |
{% for msg in messages %}
|
42 |
-
<div class="message source-{{ msg.source }}
|
43 |
<div>
|
44 |
-
|
45 |
{% if msg.hidden %}<span class="private"></span>{% endif %}
|
|
|
46 |
</div>
|
47 |
<div>
|
48 |
-
Пользователь: {% if msg.username %}<b>{{ msg.username }}</b>{% endif %} ({{ msg.user_did }})
|
49 |
</div>
|
50 |
<hr>
|
51 |
<div>{{ msg.text }}</div>
|
|
|
39 |
<hr>
|
40 |
|
41 |
{% for msg in messages %}
|
42 |
+
<div class="message source-{{ msg.source }}">
|
43 |
<div>
|
44 |
+
{% if msg.user_did == request.session['did'] %}<span class="from-self"></span>{% endif %}
|
45 |
{% if msg.hidden %}<span class="private"></span>{% endif %}
|
46 |
+
Источник: <i>{{ msg.source }}</i> — {{ msg.timestamp[:19].replace('T', ' ') }}
|
47 |
</div>
|
48 |
<div>
|
49 |
+
Пользователь: {% if msg.username %}<b>{{ msg.username }}</b>{% endif %} {% if msg.user_did !="" %}({{ msg.user_did }}){% endif %}
|
50 |
</div>
|
51 |
<hr>
|
52 |
<div>{{ msg.text }}</div>
|
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/notebook/templates/messages.html
CHANGED
@@ -41,11 +41,11 @@
|
|
41 |
{% for msg in messages %}
|
42 |
<div class="message source-{{ msg.source }} {% if msg.user_did == request.session['did'] %}from-self{% endif %}">
|
43 |
<div>
|
44 |
-
<
|
45 |
{% if msg.hidden %}<span class="private"></span>{% endif %}
|
46 |
</div>
|
47 |
<div>
|
48 |
-
|
49 |
</div>
|
50 |
<hr>
|
51 |
<div>{{ msg.text }}</div>
|
|
|
41 |
{% for msg in messages %}
|
42 |
<div class="message source-{{ msg.source }} {% if msg.user_did == request.session['did'] %}from-self{% endif %}">
|
43 |
<div>
|
44 |
+
Источник: <i>{{ msg.source }}</i> — {{ msg.timestamp }}
|
45 |
{% if msg.hidden %}<span class="private"></span>{% endif %}
|
46 |
</div>
|
47 |
<div>
|
48 |
+
Пользователь: {% if msg.username %}<b>{{ msg.username }}</b>{% endif %} ({{ msg.user_did }})
|
49 |
</div>
|
50 |
<hr>
|
51 |
<div>{{ msg.text }}</div>
|
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/notebook/templates/messages.html
CHANGED
@@ -45,9 +45,9 @@
|
|
45 |
{% if msg.hidden %}<span class="private"></span>{% endif %}
|
46 |
</div>
|
47 |
<div>
|
48 |
-
участник: {{ msg.user_did[:10] }}...
|
49 |
-
{% if msg.username %}({{ msg.username }}){% endif %}
|
50 |
</div>
|
|
|
51 |
<div>{{ msg.text }}</div>
|
52 |
</div>
|
53 |
{% endfor %}
|
|
|
45 |
{% if msg.hidden %}<span class="private"></span>{% endif %}
|
46 |
</div>
|
47 |
<div>
|
48 |
+
участник: {% if msg.username %}<b>{{ msg.username }}</b>{% endif %} ({{ msg.user_did[:10] }})...
|
|
|
49 |
</div>
|
50 |
+
<hr>
|
51 |
<div>{{ msg.text }}</div>
|
52 |
</div>
|
53 |
{% endfor %}
|
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/notebook/templates/messages.html
CHANGED
@@ -45,7 +45,7 @@
|
|
45 |
{% if msg.hidden %}<span class="private"></span>{% endif %}
|
46 |
</div>
|
47 |
<div>
|
48 |
-
|
49 |
{% if msg.username %}({{ msg.username }}){% endif %}
|
50 |
</div>
|
51 |
<div>{{ msg.text }}</div>
|
|
|
45 |
{% if msg.hidden %}<span class="private"></span>{% endif %}
|
46 |
</div>
|
47 |
<div>
|
48 |
+
участник: {{ msg.user_did[:10] }}...
|
49 |
{% if msg.username %}({{ msg.username }}){% endif %}
|
50 |
</div>
|
51 |
<div>{{ msg.text }}</div>
|
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/hf_repo/agents/notebook/views.py
CHANGED
@@ -45,14 +45,9 @@ def show_messages(request: Request, only_personal: bool = False):
|
|
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,
|
55 |
-
is_operator=is_operator,
|
56 |
only_personal=only_personal
|
57 |
)
|
58 |
return templates.TemplateResponse("messages.html", {
|
|
|
45 |
if not did:
|
46 |
return RedirectResponse("/login", status_code=303)
|
47 |
|
|
|
|
|
|
|
|
|
48 |
messages = storage.get_notes(
|
49 |
limit=50,
|
50 |
user_did=did,
|
|
|
51 |
only_personal=only_personal
|
52 |
)
|
53 |
return templates.TemplateResponse("messages.html", {
|
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/hf_repo/hf_repo/agents/tools/storage.py
CHANGED
@@ -714,38 +714,32 @@ class Storage:
|
|
714 |
""", (content, user_did, source, timestamp, hidden))
|
715 |
self.conn.commit()
|
716 |
|
717 |
-
def get_notes(self, limit=50, user_did="anon",
|
718 |
cursor = self.conn.cursor()
|
719 |
|
720 |
-
if
|
|
|
721 |
query = """
|
722 |
-
SELECT id, text, source, user_did, timestamp, hidden
|
723 |
-
FROM notes
|
724 |
-
|
|
|
|
|
725 |
LIMIT ?
|
726 |
"""
|
727 |
-
cursor.execute(query, (limit
|
728 |
else:
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
# Публичные и личные
|
741 |
-
query = """
|
742 |
-
SELECT id, text, source, user_did, timestamp, hidden
|
743 |
-
FROM notes
|
744 |
-
WHERE (user_did = ? OR user_did = 'ALL') AND hidden = 0
|
745 |
-
ORDER BY timestamp DESC
|
746 |
-
LIMIT ?
|
747 |
-
"""
|
748 |
-
cursor.execute(query, (user_did, limit))
|
749 |
|
750 |
return [dict(row) for row in cursor.fetchall()]
|
751 |
|
@@ -790,6 +784,21 @@ class Storage:
|
|
790 |
}
|
791 |
return None
|
792 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
793 |
# Утилиты
|
794 |
|
795 |
def close(self):
|
|
|
714 |
""", (content, user_did, source, timestamp, hidden))
|
715 |
self.conn.commit()
|
716 |
|
717 |
+
def get_notes(self, limit=50, user_did="anon", only_personal=False):
|
718 |
cursor = self.conn.cursor()
|
719 |
|
720 |
+
if only_personal:
|
721 |
+
# Только личные (скрытые) сообщения пользователя
|
722 |
query = """
|
723 |
+
SELECT n.id, n.text, n.source, n.user_did, u.username, n.timestamp, n.hidden
|
724 |
+
FROM notes n
|
725 |
+
LEFT JOIN users u ON n.user_did = u.did
|
726 |
+
WHERE n.user_did = ? AND n.hidden = 1
|
727 |
+
ORDER BY n.timestamp DESC
|
728 |
LIMIT ?
|
729 |
"""
|
730 |
+
cursor.execute(query, (user_did, limit))
|
731 |
else:
|
732 |
+
# Личные сообщения + публичные от user/llm, которые не скрыты
|
733 |
+
query = """
|
734 |
+
SELECT n.id, n.text, n.source, n.user_did, u.username, n.timestamp, n.hidden
|
735 |
+
FROM notes n
|
736 |
+
LEFT JOIN users u ON n.user_did = u.did
|
737 |
+
WHERE n.user_did = ?
|
738 |
+
OR ((n.source = 'user' OR n.source = 'llm') AND n.hidden = 0)
|
739 |
+
ORDER BY n.timestamp DESC
|
740 |
+
LIMIT ?
|
741 |
+
"""
|
742 |
+
cursor.execute(query, (user_did, limit))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
743 |
|
744 |
return [dict(row) for row in cursor.fetchall()]
|
745 |
|
|
|
784 |
}
|
785 |
return None
|
786 |
|
787 |
+
def get_user_info_by_did(self, did: str) -> dict | None:
|
788 |
+
cursor = self.conn.cursor()
|
789 |
+
cursor.execute(
|
790 |
+
"SELECT username, mail, operator FROM users WHERE did = ?",
|
791 |
+
(did,)
|
792 |
+
)
|
793 |
+
result = cursor.fetchone()
|
794 |
+
if result:
|
795 |
+
return {
|
796 |
+
"username": result["username"],
|
797 |
+
"mail": result["mail"],
|
798 |
+
"operator": result["operator"]
|
799 |
+
}
|
800 |
+
return None
|
801 |
+
|
802 |
# Утилиты
|
803 |
|
804 |
def close(self):
|
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/hf_repo/hf_repo/hf_repo/hf_repo/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 |
-
|
|
|
|
|
|
|
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=
|
65 |
):
|
66 |
did = request.session.get("did", "anon")
|
67 |
-
is_hidden = 1 if hidden else 0
|
68 |
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
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")
|
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/hf_repo/hf_repo/hf_repo/hf_repo/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/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/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/login.html
CHANGED
@@ -1,6 +1,14 @@
|
|
1 |
-
|
2 |
-
<
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% if error %}
|
2 |
+
<p style="color:red">{{ error }}</p>
|
3 |
+
{% endif %}
|
4 |
+
|
5 |
+
<table>
|
6 |
+
<caption>Вход</caption>
|
7 |
+
<form method="post">
|
8 |
+
<tr><th><label>Email:</th><td><input type="email" name="mail" required></label></td></tr>
|
9 |
+
<tr><th><label>Пароль:</th><td><input type="password" name="password" required></label></td></tr>
|
10 |
+
<tr><th colspan="2"><button type="submit">Войти</button></th></tr>
|
11 |
+
</form>
|
12 |
+
</table>
|
13 |
+
|
14 |
+
<hr>Нет учетки: <a href="/register">Зарегистрироваться</a>
|
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/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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 |
-
<
|
29 |
-
|
30 |
-
</label><br>
|
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>
|
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/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/notebook/templates/register.html
CHANGED
@@ -1,7 +1,15 @@
|
|
1 |
-
|
2 |
-
<
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% if error %}
|
2 |
+
<p style="color:red">{{ error }}</p>
|
3 |
+
{% endif %}
|
4 |
+
|
5 |
+
<table>
|
6 |
+
<caption>Регистрация</caption>
|
7 |
+
<form method="post">
|
8 |
+
<tr><th><label>Имя:</th><td><input type="text" name="username" required></label></td></tr>
|
9 |
+
<tr><th><label>Email:</th><td><input type="email" name="mail" required></label></td></tr>
|
10 |
+
<tr><th><label>Пароль:</th><td><input type="password" name="password" required></label></td></tr>
|
11 |
+
<tr><th colspan="2"><button type="submit">Зарегистрироваться</button></th></tr>
|
12 |
+
</form>
|
13 |
+
</table>
|
14 |
+
|
15 |
+
<hr>Есть учетка: <a href="/login">Войти</a>
|
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/hf_repo/hf_repo/hf_repo/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 =
|
756 |
try:
|
757 |
self.conn.execute(
|
758 |
"INSERT INTO users (username, mail, password_hash, did) VALUES (?, ?, ?, ?)",
|
759 |
-
(username, mail,
|
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,7 +772,7 @@ class Storage:
|
|
772 |
)
|
773 |
result = cursor.fetchone()
|
774 |
if result:
|
775 |
-
return result["password_hash"]
|
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/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/hf_repo/hf_repo/hf_repo/agents/config.yml
CHANGED
@@ -1,44 +1,69 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
api_port: 8080
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
password: password
|
11 |
-
username: user
|
12 |
-
dht_enabled: true
|
13 |
dht_port: 20784
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
llm_backends:
|
18 |
-
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
name: openai-gpt4o
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
ui_port: 8765
|
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
|
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/hf_repo/hf_repo/hf_repo/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/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/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/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/hf_repo/hf_repo/hf_repo/agents/config.yml
CHANGED
@@ -1,69 +1,44 @@
|
|
1 |
-
|
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 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
23 |
dht_port: 20784
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
llm_backends:
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
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 |
+
email: [email protected]
|
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/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/hf_repo/hf_repo/hf_repo/agents/notebook/templates/login.html
CHANGED
@@ -1,14 +1,5 @@
|
|
1 |
-
|
2 |
-
<
|
3 |
-
<
|
4 |
-
<
|
5 |
-
|
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/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/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 |
-
<
|
|
|
|
|
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
|
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/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/hf_repo/hf_repo/hf_repo/agents/notebook/templates/register.html
CHANGED
@@ -1,14 +1,6 @@
|
|
1 |
-
|
2 |
-
<
|
3 |
-
<
|
4 |
-
<
|
5 |
-
<
|
6 |
-
|
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/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/hf_repo/hf_repo/hf_repo/agents/notebook/views.py
CHANGED
@@ -1,14 +1,8 @@
|
|
1 |
-
|
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 |
-
|
20 |
-
|
|
|
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 |
-
(
|
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 |
-
|
36 |
if message.strip():
|
37 |
-
storage.
|
38 |
-
|
39 |
-
|
|
|
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 |
-
|
46 |
-
|
|
|
47 |
return RedirectResponse("/login", status_code=303)
|
48 |
|
49 |
is_operator = False # Пока не реализовано
|
50 |
messages = storage.get_notes(
|
51 |
limit=50,
|
52 |
-
user_did=
|
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=
|
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,
|
86 |
-
if storage.authenticate_user(
|
87 |
-
|
88 |
-
|
|
|
|
|
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(
|
100 |
-
|
101 |
-
|
102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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/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/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
|
754 |
-
|
755 |
-
|
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,
|
|
|
776 |
cursor = self.conn.cursor()
|
777 |
cursor.execute(
|
778 |
-
"SELECT password_hash FROM users WHERE
|
779 |
-
(
|
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/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/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/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/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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
</head>
|
7 |
<body>
|
8 |
-
<
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
|
|
|
|
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/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/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/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/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 |
-
(
|
19 |
)
|
20 |
-
return templates.TemplateResponse("chat.html", {
|
|
|
|
|
|
|
|
|
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",
|
28 |
)
|
29 |
return RedirectResponse(url="/chat", status_code=303)
|
30 |
|
31 |
@router.get("/messages")
|
32 |
-
def show_messages(request: Request):
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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/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/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/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/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 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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/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/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/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/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(
|
10 |
storage.write_note(
|
11 |
content,
|
12 |
-
role=role,
|
13 |
source=source,
|
14 |
-
user_did=user_did
|
15 |
-
tags=[]
|
16 |
)
|
17 |
-
print(f"[+] Сообщение от {
|
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.
|
|
|
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/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/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="
|
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)
|
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="
|
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/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/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/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/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,
|
704 |
timestamp = datetime.now(UTC).isoformat()
|
705 |
self.conn.execute("""
|
706 |
-
INSERT INTO notes (text,
|
707 |
-
VALUES (?, ?, ?,
|
708 |
-
""", (content,
|
709 |
self.conn.commit()
|
710 |
|
711 |
def get_notes(self, limit=50):
|
712 |
cursor = self.conn.cursor()
|
713 |
cursor.execute("""
|
714 |
-
SELECT text,
|
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/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/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/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/hf_repo/hf_repo/hf_repo/hf_repo/agents/config.yml
CHANGED
@@ -1,44 +1,69 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
api_port: 8080
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
password: password
|
11 |
-
username: user
|
12 |
-
dht_enabled: true
|
13 |
dht_port: 20784
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
llm_backends:
|
18 |
-
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
name: openai-gpt4o
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
ui_port: 8765
|
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
|
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/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/readme.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
Конфигурационные файлы: `config.yml`, `bootstrap.txt`
|
5 |
Локальная этическая модель: `ethics.yml`
|
6 |
|
7 |
-
Проверка инициализации БД - если нет, инициализация (`
|
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)*
|