File size: 5,283 Bytes
376ee15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# agents/agent.py

import argparse
import yaml
import time
import threading
import sys
from storage import Storage

def load_config(path="config.yml"):
    try:
        with open(path, "r", encoding="utf-8") as f:
            return yaml.safe_load(f)
    except FileNotFoundError:
        print(f"[Error] Config file not found: {path}")
        return {}
    except yaml.YAMLError as e:
        print(f"[Error] Failed to parse YAML config: {e}")
        return {}

def main():
    parser = argparse.ArgumentParser(description="HMP Agent CLI")
    parser.add_argument("--config", default="config.yml", help="Путь к конфигурационному файлу")
    subparsers = parser.add_subparsers(dest="command")

    # 🧠 Diary commands
    write_parser = subparsers.add_parser("write_entry", help="Добавить запись в когнитивный дневник")
    write_parser.add_argument("text")
    write_parser.add_argument("--tags", nargs="*", help="Теги (опционально)")

    read_parser = subparsers.add_parser("read_entries", help="Показать последние записи")
    read_parser.add_argument("--limit", type=int, default=5)

    search_time_parser = subparsers.add_parser("search_entries_by_time", help="Поиск записей по временному диапазону")
    search_time_parser.add_argument("--from_ts", required=True)
    search_time_parser.add_argument("--to_ts", required=True)

    # 🔗 Graph commands
    concept_parser = subparsers.add_parser("add_concept", help="Добавить концепт")
    concept_parser.add_argument("name")
    concept_parser.add_argument("--description", help="Описание (опционально)")

    link_parser = subparsers.add_parser("add_link", help="Добавить связь")
    link_parser.add_argument("--from_node", type=int, required=True)
    link_parser.add_argument("--to_node", type=int, required=True)
    link_parser.add_argument("--relation", required=True)

    expand_parser = subparsers.add_parser("expand_graph", help="Расширить граф от узла с глубиной")
    expand_parser.add_argument("--start_id", type=int, required=True)
    expand_parser.add_argument("--depth", type=int, default=1)

    args = parser.parse_args()

    # Загрузка конфигурации
    config = load_config(args.config)
    storage = Storage(config=config)

    print(f"[Agent] Запущена команда: {args.command}")

    # 📓 Diary logic
    if args.command == "write_entry":
        storage.write_entry(args.text, args.tags)
        print("✅ Запись добавлена.")

    elif args.command == "read_entries":
        for entry in storage.read_entries(limit=args.limit):
            print(f"[{entry[0]}] {entry[1]} | tags: {entry[2]} | ts: {entry[3]}")

    elif args.command == "search_entries_by_time":
        results = storage.search_entries_by_time(args.from_ts, args.to_ts)
        for e in results:
            print(f"[{e[0]}] {e[1]} | tags: {e[2]} | ts: {e[3]}")

    # 🧠 Graph logic
    elif args.command == "add_concept":
        cid = storage.add_concept(args.name, args.description)
        print(f"✅ Концепт добавлен с ID: {cid}")

    elif args.command == "add_link":
        storage.add_link(args.from_node, args.to_node, args.relation)
        print("✅ Связь добавлена.")

    elif args.command == "expand_graph":
        links = storage.expand_graph(args.start_id, args.depth)
        print(f"📐 Подграф (до глубины {args.depth}):")
        for src, tgt, rel in links:
            print(f"{src} --[{rel}]--> {tgt}")

    else:
        parser.print_help()

    storage.close()

# 🌐 MCP Agent Logic
def run_mcp_agent(config):
    print(f"[HMP-MCP] MCP-Agent '{config.get('agent_name', 'unnamed')}' запущен в DHT-режиме")

    bootstrap_path = config.get("bootstrap_file", "bootstrap.txt")
    update_interval = config.get("update_interval", 30)
    enable_api = config.get("serve_api", True)

    def load_bootstrap():
        try:
            with open(bootstrap_path, "r") as f:
                return [line.strip() for line in f if line.strip()]
        except FileNotFoundError:
            print("[Warning] bootstrap.txt не найден. Запуск без исходных узлов.")
            return []

    def update_dht():
        nodes = load_bootstrap()
        print(f"[MCP] Найдено {len(nodes)} узлов в bootstrap.txt:")
        for node in nodes:
            print(f" ↪️  Пинг {node} (заглушка)")
        print("[MCP] Обновление DHT завершено.")

    def mcp_loop():
        while True:
            update_dht()
            time.sleep(update_interval)

    threading.Thread(target=mcp_loop, daemon=True).start()

    if enable_api:
        print("[MCP] REST API (заглушка) доступен по адресу http://localhost:8000/")
        print("      В будущем: /bootstrap, /status, /reputation/:id и пр.")

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("\n[MCP] MCP-Agent завершает работу.")

if __name__ == "__main__":
    main()