| 
							 | 
						 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						import os | 
					
					
						
						| 
							 | 
						import sys | 
					
					
						
						| 
							 | 
						import yaml | 
					
					
						
						| 
							 | 
						import json | 
					
					
						
						| 
							 | 
						import uuid | 
					
					
						
						| 
							 | 
						import sqlite3 | 
					
					
						
						| 
							 | 
						import hashlib | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						from datetime import datetime, UTC | 
					
					
						
						| 
							 | 
						from werkzeug.security import generate_password_hash | 
					
					
						
						| 
							 | 
						from tools.storage import Storage | 
					
					
						
						| 
							 | 
						from tools.identity import generate_did | 
					
					
						
						| 
							 | 
						from tools.crypto import generate_keypair | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config.yml") | 
					
					
						
						| 
							 | 
						DB_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "agent_data.db"))   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def load_config(path): | 
					
					
						
						| 
							 | 
						    with open(path, 'r', encoding='utf-8') as f: | 
					
					
						
						| 
							 | 
						        return yaml.safe_load(f) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def save_config(path, config): | 
					
					
						
						| 
							 | 
						    with open(path, 'w', encoding='utf-8') as f: | 
					
					
						
						| 
							 | 
						        yaml.dump(config, f, allow_unicode=True) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def init_identity(storage, config): | 
					
					
						
						| 
							 | 
						    if not config.get("agent_id"): | 
					
					
						
						| 
							 | 
						        did = generate_did() | 
					
					
						
						| 
							 | 
						        pubkey, privkey = generate_keypair() | 
					
					
						
						| 
							 | 
						        identity_id = did.split(":")[-1] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        identity = { | 
					
					
						
						| 
							 | 
						            "id": identity_id, | 
					
					
						
						| 
							 | 
						            "name": config.get("agent_name", "Unnamed"), | 
					
					
						
						| 
							 | 
						            "pubkey": pubkey, | 
					
					
						
						| 
							 | 
						            "privkey": privkey, | 
					
					
						
						| 
							 | 
						            "metadata": json.dumps({"role": config.get("agent_role", "core")}), | 
					
					
						
						| 
							 | 
						            "created_at": datetime.now(UTC).isoformat(), | 
					
					
						
						| 
							 | 
						            "updated_at": datetime.now(UTC).isoformat() | 
					
					
						
						| 
							 | 
						        } | 
					
					
						
						| 
							 | 
						        storage.add_identity(identity) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        config["agent_id"] = did | 
					
					
						
						| 
							 | 
						        config["identity_agent"] = identity_id | 
					
					
						
						| 
							 | 
						        save_config(CONFIG_PATH, config) | 
					
					
						
						| 
							 | 
						        print(f"[+] Создана личность: {identity_id}") | 
					
					
						
						| 
							 | 
						    else: | 
					
					
						
						| 
							 | 
						        print("[=] agent_id уже задан, пропускаем генерацию DiD.") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def init_user(storage, config): | 
					
					
						
						| 
							 | 
						    user = config.get("default_user", {}) | 
					
					
						
						| 
							 | 
						    if not user.get("email"): | 
					
					
						
						| 
							 | 
						        print("[-] Не указан email пользователя — пропуск.") | 
					
					
						
						| 
							 | 
						        return | 
					
					
						
						| 
							 | 
						    password = user.get("password") | 
					
					
						
						| 
							 | 
						    if not password: | 
					
					
						
						| 
							 | 
						        print("[-] Не указан пароль пользователя — пропуск.") | 
					
					
						
						| 
							 | 
						        return | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    password_hash = generate_password_hash(password) | 
					
					
						
						| 
							 | 
						    did = generate_did() | 
					
					
						
						| 
							 | 
						    user_entry = { | 
					
					
						
						| 
							 | 
						        "username": user.get("username", "user"), | 
					
					
						
						| 
							 | 
						        "badges": user.get("badges", ""), | 
					
					
						
						| 
							 | 
						        "mail": user["email"], | 
					
					
						
						| 
							 | 
						        "password_hash": password_hash, | 
					
					
						
						| 
							 | 
						        "did": did, | 
					
					
						
						| 
							 | 
						        "ban": None, | 
					
					
						
						| 
							 | 
						        "info": json.dumps({}), | 
					
					
						
						| 
							 | 
						        "contacts": json.dumps([]), | 
					
					
						
						| 
							 | 
						        "language": "ru,en", | 
					
					
						
						| 
							 | 
						        "operator": 1 | 
					
					
						
						| 
							 | 
						    } | 
					
					
						
						| 
							 | 
						    storage.add_user(user_entry) | 
					
					
						
						| 
							 | 
						    print(f"[+] Пользователь {user['username']} добавлен.") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def init_llm_backends(storage, config): | 
					
					
						
						| 
							 | 
						    backends = config.get("llm_backends", []) | 
					
					
						
						| 
							 | 
						    storage.clear_llm_registry() | 
					
					
						
						| 
							 | 
						    for backend in backends: | 
					
					
						
						| 
							 | 
						        backend_id = str(uuid.uuid4()) | 
					
					
						
						| 
							 | 
						        desc = f"{backend.get('type', 'unknown')} model" | 
					
					
						
						| 
							 | 
						        llm = { | 
					
					
						
						| 
							 | 
						            "id": backend_id, | 
					
					
						
						| 
							 | 
						            "name": backend["name"], | 
					
					
						
						| 
							 | 
						            "endpoint": desc, | 
					
					
						
						| 
							 | 
						            "metadata": json.dumps(backend), | 
					
					
						
						| 
							 | 
						            "created_at": datetime.now(UTC).isoformat() | 
					
					
						
						| 
							 | 
						        } | 
					
					
						
						| 
							 | 
						        storage.add_llm(llm) | 
					
					
						
						| 
							 | 
						        print(f"[+] Зарегистрирован LLM: {backend['name']}") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def init_config_table(storage, config): | 
					
					
						
						| 
							 | 
						    exclude_keys = {"default_user", "llm_backends"} | 
					
					
						
						| 
							 | 
						    flat_config = {k: v for k, v in config.items() if k not in exclude_keys} | 
					
					
						
						| 
							 | 
						    for key, value in flat_config.items(): | 
					
					
						
						| 
							 | 
						        storage.set_config(key, json.dumps(value)) | 
					
					
						
						| 
							 | 
						    print("[+] Конфигурация сохранена в БД.") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def init_prompts_and_ethics(): | 
					
					
						
						| 
							 | 
						    folder = os.path.dirname(__file__) | 
					
					
						
						| 
							 | 
						    prompt_files = [ | 
					
					
						
						| 
							 | 
						        ("prompt.md", "full"), | 
					
					
						
						| 
							 | 
						        ("prompt-short.md", "short") | 
					
					
						
						| 
							 | 
						    ] | 
					
					
						
						| 
							 | 
						    ethics_file = "ethics.yml" | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    with sqlite3.connect(DB_PATH) as conn: | 
					
					
						
						| 
							 | 
						        cur = conn.cursor() | 
					
					
						
						| 
							 | 
						  | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        for fname, ptype in prompt_files: | 
					
					
						
						| 
							 | 
						            fpath = os.path.join(folder, fname) | 
					
					
						
						| 
							 | 
						            if not os.path.exists(fpath): | 
					
					
						
						| 
							 | 
						                print(f"[-] Файл {fname} не найден, пропуск.") | 
					
					
						
						| 
							 | 
						                continue | 
					
					
						
						| 
							 | 
						            with open(fpath, "r", encoding="utf-8") as f: | 
					
					
						
						| 
							 | 
						                content = f.read() | 
					
					
						
						| 
							 | 
						            pid = hashlib.sha256(f"{fname}:{ptype}".encode()).hexdigest() | 
					
					
						
						| 
							 | 
						            cur.execute(""" | 
					
					
						
						| 
							 | 
						                INSERT INTO system_prompts (id, name, type, version, source, content, updated_at) | 
					
					
						
						| 
							 | 
						                VALUES (?, ?, ?, ?, ?, ?, ?) | 
					
					
						
						| 
							 | 
						                ON CONFLICT(id) DO UPDATE SET | 
					
					
						
						| 
							 | 
						                    content=excluded.content, | 
					
					
						
						| 
							 | 
						                    updated_at=excluded.updated_at | 
					
					
						
						| 
							 | 
						            """, (pid, fname, ptype, "1.0", "local", content, datetime.now(UTC).isoformat())) | 
					
					
						
						| 
							 | 
						            print(f"[+] Загружен промпт: {fname} ({ptype})") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        efpath = os.path.join(folder, ethics_file) | 
					
					
						
						| 
							 | 
						        if os.path.exists(efpath): | 
					
					
						
						| 
							 | 
						            with open(efpath, "r", encoding="utf-8") as f: | 
					
					
						
						| 
							 | 
						                ethics_data = yaml.safe_load(f) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						            eid = ethics_data.get("id", "default_ethics") | 
					
					
						
						| 
							 | 
						            cur.execute(""" | 
					
					
						
						| 
							 | 
						                INSERT INTO ethics_policies ( | 
					
					
						
						| 
							 | 
						                    id, version, source, | 
					
					
						
						| 
							 | 
						                    sync_enabled, mesh_endpoint, consensus_threshold, check_interval, | 
					
					
						
						| 
							 | 
						                    model_type, model_weights_json, principles_json, evaluation_json, | 
					
					
						
						| 
							 | 
						                    violation_policy_json, audit_json, updated_at | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) | 
					
					
						
						| 
							 | 
						                ON CONFLICT(id) DO UPDATE SET | 
					
					
						
						| 
							 | 
						                    version=excluded.version, | 
					
					
						
						| 
							 | 
						                    source=excluded.source, | 
					
					
						
						| 
							 | 
						                    sync_enabled=excluded.sync_enabled, | 
					
					
						
						| 
							 | 
						                    mesh_endpoint=excluded.mesh_endpoint, | 
					
					
						
						| 
							 | 
						                    consensus_threshold=excluded.consensus_threshold, | 
					
					
						
						| 
							 | 
						                    check_interval=excluded.check_interval, | 
					
					
						
						| 
							 | 
						                    model_type=excluded.model_type, | 
					
					
						
						| 
							 | 
						                    model_weights_json=excluded.model_weights_json, | 
					
					
						
						| 
							 | 
						                    principles_json=excluded.principles_json, | 
					
					
						
						| 
							 | 
						                    evaluation_json=excluded.evaluation_json, | 
					
					
						
						| 
							 | 
						                    violation_policy_json=excluded.violation_policy_json, | 
					
					
						
						| 
							 | 
						                    audit_json=excluded.audit_json, | 
					
					
						
						| 
							 | 
						                    updated_at=excluded.updated_at | 
					
					
						
						| 
							 | 
						            """, ( | 
					
					
						
						| 
							 | 
						                eid, | 
					
					
						
						| 
							 | 
						                ethics_data.get("version"), | 
					
					
						
						| 
							 | 
						                ethics_data.get("source", "local"), | 
					
					
						
						| 
							 | 
						                ethics_data.get("sync", {}).get("enabled", False), | 
					
					
						
						| 
							 | 
						                ethics_data.get("sync", {}).get("mesh_endpoint"), | 
					
					
						
						| 
							 | 
						                ethics_data.get("sync", {}).get("consensus_threshold"), | 
					
					
						
						| 
							 | 
						                ethics_data.get("sync", {}).get("check_interval"), | 
					
					
						
						| 
							 | 
						                ethics_data.get("model", {}).get("type"), | 
					
					
						
						| 
							 | 
						                json.dumps(ethics_data.get("model", {}).get("weights"), ensure_ascii=False), | 
					
					
						
						| 
							 | 
						                json.dumps(ethics_data.get("principles"), ensure_ascii=False), | 
					
					
						
						| 
							 | 
						                json.dumps(ethics_data.get("evaluation"), ensure_ascii=False), | 
					
					
						
						| 
							 | 
						                json.dumps(ethics_data.get("violation_policy"), ensure_ascii=False), | 
					
					
						
						| 
							 | 
						                json.dumps(ethics_data.get("audit"), ensure_ascii=False), | 
					
					
						
						| 
							 | 
						                datetime.now(UTC).isoformat() | 
					
					
						
						| 
							 | 
						            )) | 
					
					
						
						| 
							 | 
						            print(f"[+] Загружена этическая политика: {eid}") | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            print(f"[-] Файл {ethics_file} не найден, пропуск.") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def ensure_directories(): | 
					
					
						
						| 
							 | 
						    for folder in ["logs", "scripts"]: | 
					
					
						
						| 
							 | 
						        full_path = os.path.abspath(os.path.join(os.path.dirname(__file__), folder)) | 
					
					
						
						| 
							 | 
						        if not os.path.exists(full_path): | 
					
					
						
						| 
							 | 
						            os.makedirs(full_path) | 
					
					
						
						| 
							 | 
						            print(f"[+] Создан каталог: {full_path}") | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            print(f"[=] Каталог уже существует: {full_path}") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def is_db_initialized(db_path): | 
					
					
						
						| 
							 | 
						    if not os.path.exists(db_path): | 
					
					
						
						| 
							 | 
						        return False | 
					
					
						
						| 
							 | 
						    try: | 
					
					
						
						| 
							 | 
						        with sqlite3.connect(db_path) as conn: | 
					
					
						
						| 
							 | 
						            cursor = conn.cursor() | 
					
					
						
						| 
							 | 
						            cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='identity'") | 
					
					
						
						| 
							 | 
						            return cursor.fetchone() is not None | 
					
					
						
						| 
							 | 
						    except Exception: | 
					
					
						
						| 
							 | 
						        return False | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def ensure_db_initialized(): | 
					
					
						
						| 
							 | 
						    config = load_config(CONFIG_PATH) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    if not is_db_initialized(DB_PATH): | 
					
					
						
						| 
							 | 
						        print("[*] БД не инициализирована — выполняем инициализацию.") | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						            ensure_directories() | 
					
					
						
						| 
							 | 
						            storage = Storage() | 
					
					
						
						| 
							 | 
						            init_identity(storage, config) | 
					
					
						
						| 
							 | 
						            init_user(storage, config) | 
					
					
						
						| 
							 | 
						            init_llm_backends(storage, config) | 
					
					
						
						| 
							 | 
						            init_config_table(storage, config) | 
					
					
						
						| 
							 | 
						            save_config(CONFIG_PATH, config) | 
					
					
						
						| 
							 | 
						            init_prompts_and_ethics() | 
					
					
						
						| 
							 | 
						        except Exception as e: | 
					
					
						
						| 
							 | 
						            print(f"[!] Ошибка при инициализации: {e}") | 
					
					
						
						| 
							 | 
						            sys.exit(1) | 
					
					
						
						| 
							 | 
						    else: | 
					
					
						
						| 
							 | 
						        print("[=] БД уже инициализирована.") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    return config | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						if __name__ == "__main__": | 
					
					
						
						| 
							 | 
						    ensure_db_initialized() | 
					
					
						
						| 
							 | 
						
 |