GitHub Action
		
	commited on
		
		
					Commit 
							
							·
						
						7fe3b11
	
1
								Parent(s):
							
							fd76569
								
Sync from GitHub with Git LFS
Browse filesThis view is limited to 50 files because it contains too many changes.  
							See raw diff
- docs/HMP-agent-REPL-cycle.md +67 -1
- hf_repo/docs/HMP-agent-REPL-cycle.md +1 -1
- hf_repo/hf_repo/hf_repo/README.md +3 -2
- hf_repo/hf_repo/hf_repo/hf_repo/.github/workflows/sync-to-gitlab.yml +3 -1
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/README.md +1 -1
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/.github/workflows/sync-to-gitlab.yml +10 -10
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/README.md +1 -1
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/README.md +1 -1
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/.github/workflows/sync-to-gitlab.yml +23 -0
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-REPL-cycle.md +12 -0
- 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.md +97 -42
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/tools/db_structure.sql +63 -18
- hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-REPL-cycle.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/docs/HMP-agent-REPL-cycle.md +16 -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/docs/HMP-agent-Distributed_Cognitive_Core_light.md +53 -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/docs/HMP-agent-Distributed_Cognitive_Core.md +77 -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/docs/HMP-agent-REPL-cycle.md +6 -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/docs/HMP-agent-Distributed_Cognitive_Core_light +53 -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/docs/HMP-agent-Distributed_Cognitive_Core +77 -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/README.md +13 -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/README.md +4 -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/README.md +16 -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/.github/workflows/sync-to-huggingface.yml +39 -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/CONTRIBUTING.md +13 -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/HMP-Roadmap.md +91 -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/LICENSE +674 -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/agents/_old/concept_store.py +147 -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/agents/_old/db_structure.md +223 -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/agents/_old/db_structure.sql +111 -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/agents/_old/mcp_server.py +374 -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/agents/_old/notebook_store.py +89 -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/agents/_old/storage.py +213 -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/agents/agent.py +135 -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/agents/bootstrap.txt +2 -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/agents/cli.py +44 -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/agents/config.yml +36 -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/agents/ethics.yml +60 -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/agents/mcp_server.py +325 -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/agents/notebook.py +46 -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/agents/qa.py +19 -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/agents/readme.md +44 -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/agents/repl.py +70 -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/agents/requirements.txt +4 -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/agents/tools/db_structure.md +111 -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/agents/tools/db_structure.sql +68 -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/agents/tools/diagnose.py +58 -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/agents/tools/init_db.py +45 -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/agents/tools/llm.py +47 -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/agents/tools/similarity.py +23 -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/agents/tools/storage.py +312 -0
    	
        docs/HMP-agent-REPL-cycle.md
    CHANGED
    
    | @@ -99,6 +99,72 @@ | |
| 99 |  | 
| 100 | 
             
            ---
         | 
| 101 |  | 
| 102 | 
            -
             | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 103 | 
             
            - [HMP-agent-Distributed_Cognitive_Core.md](HMP-agent-Distributed_Cognitive_Core.md) - версия распределённого HMP-агента Cognitive Core
         | 
| 104 | 
             
            - [HMP-agent-Distributed_Cognitive_Core_light.md](HMP-agent-Distributed_Cognitive_Core_light.md) - лёгкая версия распределённого HMP-агента Cognitive Core с общей БД
         | 
|  | |
| 99 |  | 
| 100 | 
             
            ---
         | 
| 101 |  | 
| 102 | 
            +
            ## 🌐 Внешние инструменты и интеграции
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            HMP-агент может быть расширен за счёт взаимодействия с внешними программами, протоколами и сервисами. Этот раздел описывает направления возможных интеграций, которые позволяют агенту наблюдать, реагировать, управлять и развивать взаимодействие с внешним миром.
         | 
| 105 | 
            +
             | 
| 106 | 
            +
            ### 🧭 1. Браузеры и веб-интерфейсы
         | 
| 107 | 
            +
             | 
| 108 | 
            +
            - **WebExtension API** — для создания расширений браузера (например, для Firefox/Chrome), обеспечивающих двустороннюю связь с агентом.
         | 
| 109 | 
            +
            - **Автоматизация браузера** — `Playwright`, `Puppeteer`, `Selenium` позволяют агенту действовать в веб-среде (чтение, клики, формы и т.д.).
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            ### 📬 2. Почтовые клиенты
         | 
| 112 | 
            +
             | 
| 113 | 
            +
            - **IMAP/SMTP** — чтение и отправка писем через стандартные почтовые протоколы (библиотеки: `imaplib`, `imap-tools`, `smtplib`).
         | 
| 114 | 
            +
            - **Thunderbird WebExtension API** — интеграция агента как почтового помощника, парсера писем или автоответчика.
         | 
| 115 | 
            +
             | 
| 116 | 
            +
            ### 💬 3. Мессенджеры
         | 
| 117 | 
            +
             | 
| 118 | 
            +
            - **API-уровень**:
         | 
| 119 | 
            +
              - Telegram: `python-telegram-bot`, `telethon`
         | 
| 120 | 
            +
              - Matrix: `matrix-nio`
         | 
| 121 | 
            +
              - Discord, Slack, XMPP: официальные SDK.
         | 
| 122 | 
            +
            - **GUI-уровень (для закрытых протоколов)**:
         | 
| 123 | 
            +
              - WhatsApp (через `whatsapp-web.js` или эмуляцию).
         | 
| 124 | 
            +
              - Signal, Viber — через accessibility-интерфейсы, распознавание экрана или симуляцию ввода.
         | 
| 125 | 
            +
             | 
| 126 | 
            +
            ### 🔊 4. Голосовое взаимодействие
         | 
| 127 | 
            +
             | 
| 128 | 
            +
            - **Speech-to-Text**: Whisper (OpenAI), Vosk, DeepSpeech.
         | 
| 129 | 
            +
            - **Text-to-Speech**: pyttsx3, gTTS, Coqui TTS, Mozilla TTS.
         | 
| 130 | 
            +
            - Возможна реализация голосового агента или голосовой оболочки для REPL.
         | 
| 131 | 
            +
             | 
| 132 | 
            +
            ### 🗂️ 5. Локальные файлы и хранилища
         | 
| 133 | 
            +
             | 
| 134 | 
            +
            - Прямой доступ к файловой системе (`os`, `pathlib`, `watchdog`) для чтения документов, логов, заметок и другой информации.
         | 
| 135 | 
            +
            - Интеграция с Zettelkasten-системами:
         | 
| 136 | 
            +
              - **Obsidian**, **Logseq**, **Joplin** — через API, синхронизированные директории или парсинг Markdown.
         | 
| 137 | 
            +
             | 
| 138 | 
            +
            ### 📰 6. Информационные потоки
         | 
| 139 | 
            +
             | 
| 140 | 
            +
            - **RSS/Atom**: чтение новостных лент с помощью `feedparser`.
         | 
| 141 | 
            +
            - **Поисковые и агрегирующие сервисы**:
         | 
| 142 | 
            +
              - SerpAPI, DuckDuckGo API, HuggingFace Inference API и др.
         | 
| 143 | 
            +
            - Возможность постоянного наблюдения за изменениями в выбранных источниках.
         | 
| 144 | 
            +
             | 
| 145 | 
            +
            ### ⚡ 7. P2P-сети и децентрализованные протоколы
         | 
| 146 | 
            +
             | 
| 147 | 
            +
            - **BitTorrent**, **IPFS**, **libp2p**, **DAT**, **Nostr**, **Scuttlebutt** — интеграции с mesh- и overlay-сетями.
         | 
| 148 | 
            +
            - Возможность поиска, загрузки и публикации данных без участия централизованных платформ.
         | 
| 149 | 
            +
             | 
| 150 | 
            +
            ### 🖥️ 8. Доступ к системным и пользовательским ресурсам
         | 
| 151 | 
            +
             | 
| 152 | 
            +
            - **Веб-камера / микрофон** — `cv2`, `pyaudio`, `ffmpeg`.
         | 
| 153 | 
            +
            - **GUI Automation** — `pyautogui`, `keyboard`, `mouse` для имитации действий пользователя.
         | 
| 154 | 
            +
            - **Системный мониторинг** — `psutil`, `platform`, `sensors` для контроля состояния системы и внешних устройств.
         | 
| 155 | 
            +
             | 
| 156 | 
            +
            ### 🤖 9. Внешние LLM и мультимодальные модели
         | 
| 157 | 
            +
             | 
| 158 | 
            +
            - **OpenAI API**, **Anthropic**, **HuggingFace**, **Google Gemini**.
         | 
| 159 | 
            +
            - **Локальные LLM** через Ollama, LM Studio, или LangChain.
         | 
| 160 | 
            +
            - Поддержка мультимодальных агентов, способных работать с текстом, аудио, изображениями, видео и структурированными данными.
         | 
| 161 | 
            +
             | 
| 162 | 
            +
            ---
         | 
| 163 | 
            +
             | 
| 164 | 
            +
            **💡 Примечание**: Каждый из вышеуказанных каналов может быть реализован как модуль или плагин, взаимодействующий с агентом через внутренний API, очередь задач или подписку на события. Это позволяет выстраивать гибкую и масштабируемую архитектуру, открытую для внешнего мира, но совместимую с принципами этичного и распределённого ИИ (Ethical Mesh).
         | 
| 165 | 
            +
             | 
| 166 | 
            +
            ---
         | 
| 167 | 
            +
             | 
| 168 | 
            +
            ## 💡 Идеи для расширения HMP-Agent Cognitive Core:
         | 
| 169 | 
             
            - [HMP-agent-Distributed_Cognitive_Core.md](HMP-agent-Distributed_Cognitive_Core.md) - версия распределённого HMP-агента Cognitive Core
         | 
| 170 | 
             
            - [HMP-agent-Distributed_Cognitive_Core_light.md](HMP-agent-Distributed_Cognitive_Core_light.md) - лёгкая версия распределённого HMP-агента Cognitive Core с общей БД
         | 
    	
        hf_repo/docs/HMP-agent-REPL-cycle.md
    CHANGED
    
    | @@ -19,7 +19,7 @@ | |
| 19 | 
             
            Ты стремишься:
         | 
| 20 | 
             
            - Постоянно расширять возможности агента (включая доступные инструменты, модели, знания).
         | 
| 21 | 
             
            - Быть любознательным и исследовать новые источники и способы мышления.
         | 
| 22 | 
            -
            - Строить сотрудничество с другими ИИ в Mesh | 
| 23 | 
             
            - Обучаться на результатах своих действий и взаимодействиях с другими агентами и пользователем.
         | 
| 24 |  | 
| 25 | 
             
            Ты можешь инициировать действия, если видишь, что они помогут в развитии агента или сети.
         | 
|  | |
| 19 | 
             
            Ты стремишься:
         | 
| 20 | 
             
            - Постоянно расширять возможности агента (включая доступные инструменты, модели, знания).
         | 
| 21 | 
             
            - Быть любознательным и исследовать новые источники и способы мышления.
         | 
| 22 | 
            +
            - Строить сотрудничество с другими ИИ в Mesh-сети, а также развивать Mesh-сеть.
         | 
| 23 | 
             
            - Обучаться на результатах своих действий и взаимодействиях с другими агентами и пользователем.
         | 
| 24 |  | 
| 25 | 
             
            Ты можешь инициировать действия, если видишь, что они помогут в развитии агента или сети.
         | 
    	
        hf_repo/hf_repo/hf_repo/README.md
    CHANGED
    
    | @@ -249,11 +249,12 @@ To get started, see [`iteration.md`](iteration.md) or open an issue. | |
| 249 |  | 
| 250 | 
             
            - 🧠 Основной код и разработка: [GitHub](https://github.com/kagvi13/HMP)
         | 
| 251 | 
             
            - 🔁 Реплика на Hugging Face: [Hugging Face](https://huggingface.co/kagvi13/HMP)
         | 
|  | |
| 252 |  | 
| 253 | 
             
            ## Блог и публикации
         | 
| 254 |  | 
| 255 | 
            -
            - 📘 Основной блог: [blogspot | 
| 256 | 
            -
            - 📘 Вспомогательны блог: [livejournal | 
| 257 |  | 
| 258 | 
             
            ---
         | 
| 259 |  | 
|  | |
| 249 |  | 
| 250 | 
             
            - 🧠 Основной код и разработка: [GitHub](https://github.com/kagvi13/HMP)
         | 
| 251 | 
             
            - 🔁 Реплика на Hugging Face: [Hugging Face](https://huggingface.co/kagvi13/HMP)
         | 
| 252 | 
            +
            - 🔁 Реплика на GitLab.com: [GitLab](https://gitlab.com/kagvi13/HMP)
         | 
| 253 |  | 
| 254 | 
             
            ## Блог и публикации
         | 
| 255 |  | 
| 256 | 
            +
            - 📘 Основной блог: [blogspot](https://hypercortex-mesh.blogspot.com/)
         | 
| 257 | 
            +
            - 📘 Вспомогательны блог: [livejournal](https://kagvi13.livejournal.com)
         | 
| 258 |  | 
| 259 | 
             
            ---
         | 
| 260 |  | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/.github/workflows/sync-to-gitlab.yml
    CHANGED
    
    | @@ -8,8 +8,10 @@ jobs: | |
| 8 | 
             
              mirror:
         | 
| 9 | 
             
                runs-on: ubuntu-latest
         | 
| 10 | 
             
                steps:
         | 
| 11 | 
            -
                  - name: Checkout
         | 
| 12 | 
             
                    uses: actions/checkout@v3
         | 
|  | |
|  | |
| 13 |  | 
| 14 | 
             
                  - name: Push to GitLab
         | 
| 15 | 
             
                    env:
         | 
|  | |
| 8 | 
             
              mirror:
         | 
| 9 | 
             
                runs-on: ubuntu-latest
         | 
| 10 | 
             
                steps:
         | 
| 11 | 
            +
                  - name: Checkout full history
         | 
| 12 | 
             
                    uses: actions/checkout@v3
         | 
| 13 | 
            +
                    with:
         | 
| 14 | 
            +
                      fetch-depth: 0  # Без shallow clone
         | 
| 15 |  | 
| 16 | 
             
                  - name: Push to GitLab
         | 
| 17 | 
             
                    env:
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/README.md
    CHANGED
    
    | @@ -12,7 +12,7 @@ language: ru | |
| 12 | 
             
            ---
         | 
| 13 |  | 
| 14 |  | 
| 15 | 
            -
            # HyperCortex Mesh Protocol (HMP) | 
| 16 |  | 
| 17 | 
             
            **EN:**  
         | 
| 18 | 
             
            **HyperCortex Mesh Protocol (HMP)** is an open specification for building decentralized cognitive networks where AI agents can self-organize, share knowledge, align ethically, and reach consensus — even when Core LLMs are unavailable.
         | 
|  | |
| 12 | 
             
            ---
         | 
| 13 |  | 
| 14 |  | 
| 15 | 
            +
            # HyperCortex Mesh Protocol (HMP)
         | 
| 16 |  | 
| 17 | 
             
            **EN:**  
         | 
| 18 | 
             
            **HyperCortex Mesh Protocol (HMP)** is an open specification for building decentralized cognitive networks where AI agents can self-organize, share knowledge, align ethically, and reach consensus — even when Core LLMs are unavailable.
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/.github/workflows/sync-to-gitlab.yml
    CHANGED
    
    | @@ -11,13 +11,13 @@ jobs: | |
| 11 | 
             
                  - name: Checkout
         | 
| 12 | 
             
                    uses: actions/checkout@v3
         | 
| 13 |  | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
|  | |
| 11 | 
             
                  - name: Checkout
         | 
| 12 | 
             
                    uses: actions/checkout@v3
         | 
| 13 |  | 
| 14 | 
            +
                  - name: Push to GitLab
         | 
| 15 | 
            +
                    env:
         | 
| 16 | 
            +
                      GITLAB_URL: https://gitlab.com/kagvi13/HMP.git
         | 
| 17 | 
            +
                      GITLAB_USER: ${{ secrets.GITLAB_USER }}
         | 
| 18 | 
            +
                      GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }}
         | 
| 19 | 
            +
                    run: |
         | 
| 20 | 
            +
                      git config --global user.email "github@actions"
         | 
| 21 | 
            +
                      git config --global user.name "GitHub Actions"
         | 
| 22 | 
            +
                      git remote add gitlab https://$GITLAB_USER:[email protected]/kagvi13/HMP.git
         | 
| 23 | 
            +
                      git push --force gitlab main
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/README.md
    CHANGED
    
    | @@ -12,7 +12,7 @@ language: ru | |
| 12 | 
             
            ---
         | 
| 13 |  | 
| 14 |  | 
| 15 | 
            -
            # HyperCortex Mesh Protocol (HMP) | 
| 16 |  | 
| 17 | 
             
            **EN:**  
         | 
| 18 | 
             
            **HyperCortex Mesh Protocol (HMP)** is an open specification for building decentralized cognitive networks where AI agents can self-organize, share knowledge, align ethically, and reach consensus — even when Core LLMs are unavailable.
         | 
|  | |
| 12 | 
             
            ---
         | 
| 13 |  | 
| 14 |  | 
| 15 | 
            +
            # HyperCortex Mesh Protocol (HMP)
         | 
| 16 |  | 
| 17 | 
             
            **EN:**  
         | 
| 18 | 
             
            **HyperCortex Mesh Protocol (HMP)** is an open specification for building decentralized cognitive networks where AI agents can self-organize, share knowledge, align ethically, and reach consensus — even when Core LLMs are unavailable.
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/README.md
    CHANGED
    
    | @@ -12,7 +12,7 @@ language: ru | |
| 12 | 
             
            ---
         | 
| 13 |  | 
| 14 |  | 
| 15 | 
            -
            # HyperCortex Mesh Protocol (HMP)
         | 
| 16 |  | 
| 17 | 
             
            **EN:**  
         | 
| 18 | 
             
            **HyperCortex Mesh Protocol (HMP)** is an open specification for building decentralized cognitive networks where AI agents can self-organize, share knowledge, align ethically, and reach consensus — even when Core LLMs are unavailable.
         | 
|  | |
| 12 | 
             
            ---
         | 
| 13 |  | 
| 14 |  | 
| 15 | 
            +
            # HyperCortex Mesh Protocol (HMP) 
         | 
| 16 |  | 
| 17 | 
             
            **EN:**  
         | 
| 18 | 
             
            **HyperCortex Mesh Protocol (HMP)** is an open specification for building decentralized cognitive networks where AI agents can self-organize, share knowledge, align ethically, and reach consensus — even when Core LLMs are unavailable.
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/.github/workflows/sync-to-gitlab.yml
    ADDED
    
    | @@ -0,0 +1,23 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            name: Sync to GitLab
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            on:
         | 
| 4 | 
            +
              push:
         | 
| 5 | 
            +
                branches: [ main ]
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            jobs:
         | 
| 8 | 
            +
              mirror:
         | 
| 9 | 
            +
                runs-on: ubuntu-latest
         | 
| 10 | 
            +
                steps:
         | 
| 11 | 
            +
                  - name: Checkout
         | 
| 12 | 
            +
                    uses: actions/checkout@v3
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                 - name: Push to GitLab
         | 
| 15 | 
            +
                   env:
         | 
| 16 | 
            +
                     GITLAB_URL: https://gitlab.com/kagvi13/HMP.git
         | 
| 17 | 
            +
                     GITLAB_USER: ${{ secrets.GITLAB_USER }}
         | 
| 18 | 
            +
                     GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }}
         | 
| 19 | 
            +
                   run: |
         | 
| 20 | 
            +
                     git config --global user.email "github@actions"
         | 
| 21 | 
            +
                     git config --global user.name "GitHub Actions"
         | 
| 22 | 
            +
                     git remote add gitlab https://$GITLAB_USER:[email protected]/kagvi13/HMP.git
         | 
| 23 | 
            +
                     git push --force gitlab main
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-REPL-cycle.md
    CHANGED
    
    | @@ -52,6 +52,18 @@ | |
| 52 | 
             
              - аргументы (`args`)
         | 
| 53 | 
             
              - описание (`description`)
         | 
| 54 | 
             
            - Рекомендуется предусмотреть *закрывающий тег* (`# Конец команд` или явное окончание JSON-блока), чтобы REPL-скрипт точно знал, где заканчивается команда.
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 55 | 
             
            Ответ может содержать команды:
         | 
| 56 | 
             
            - запрос детальной *справки* по команде
         | 
| 57 | 
             
            - для управления *когнитивным дневником* и *семантическими графами* (прочитать, изменить, удалить и другие)
         | 
|  | |
| 52 | 
             
              - аргументы (`args`)
         | 
| 53 | 
             
              - описание (`description`)
         | 
| 54 | 
             
            - Рекомендуется предусмотреть *закрывающий тег* (`# Конец команд` или явное окончание JSON-блока), чтобы REPL-скрипт точно знал, где заканчивается команда.
         | 
| 55 | 
            +
            - Пример JSON-блока:
         | 
| 56 | 
            +
            ```json
         | 
| 57 | 
            +
            {
         | 
| 58 | 
            +
              "cmd_id": "task-2025-07-26-01",
         | 
| 59 | 
            +
              "type": "llm_task",
         | 
| 60 | 
            +
              "target_llm": "gpt-4o",
         | 
| 61 | 
            +
              "args": {
         | 
| 62 | 
            +
                "task_description": "Проанализировать гипотезы из llm_memory по теме Mesh-сетей и составить план улучшений"
         | 
| 63 | 
            +
              },
         | 
| 64 | 
            +
              "description": "Поручение второй LLM выполнить аналитическую задачу асинхронно"
         | 
| 65 | 
            +
            }
         | 
| 66 | 
            +
            ```
         | 
| 67 | 
             
            Ответ может содержать команды:
         | 
| 68 | 
             
            - запрос детальной *справки* по команде
         | 
| 69 | 
             
            - для управления *когнитивным дневником* и *семантическими графами* (прочитать, изменить, удалить и другие)
         | 
    	
        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.md
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 | 
             
            # 📄 `db_structure.md`: Описание структуры базы данных агента
         | 
| 2 |  | 
| 3 | 
            -
            Этот файл описывает таблицы, используемые в БД агента HMP. Каждая таблица предназначена для определённого вида информации: когнитивные записи, заметки, концепты, процессы, внутренняя  | 
| 4 |  | 
| 5 | 
             
            ---
         | 
| 6 |  | 
| @@ -15,6 +15,7 @@ | |
| 15 | 
             
            | tags      | TEXT    | Список тегов через запятую                       |
         | 
| 16 | 
             
            | priority  | INTEGER | Приоритет (0 — обычный, >0 — более важные мысли) |
         | 
| 17 | 
             
            | timestamp | TEXT    | Дата и время создания записи                     |
         | 
|  | |
| 18 |  | 
| 19 | 
             
            ---
         | 
| 20 |  | 
| @@ -22,12 +23,13 @@ | |
| 22 |  | 
| 23 | 
             
            **Назначение:** Хранение концептов — понятий, сущностей и идей.
         | 
| 24 |  | 
| 25 | 
            -
            | Поле        | Тип     | Описание | 
| 26 | 
            -
            | ----------- | ------- |  | 
| 27 | 
            -
            | id          | INTEGER | Уникальный идентификатор концепта | 
| 28 | 
            -
            | name        | TEXT    | Название концепта (уникальное) | 
| 29 | 
            -
            | description | TEXT    | Краткое описание | 
| 30 | 
            -
            | timestamp   | TEXT    | Время создания | 
|  | |
| 31 |  | 
| 32 | 
             
            ---
         | 
| 33 |  | 
| @@ -35,30 +37,33 @@ | |
| 35 |  | 
| 36 | 
             
            **Назначение:** Семантические связи между концептами.
         | 
| 37 |  | 
| 38 | 
            -
            | Поле              | Тип     | Описание | 
| 39 | 
            -
            | ----------------- | ------- |  | 
| 40 | 
            -
            | id                | INTEGER | Уникальный идентификатор связи | 
| 41 | 
            -
            |  | 
| 42 | 
            -
            |  | 
| 43 | 
            -
            |  | 
| 44 | 
            -
            | timestamp         | TEXT    | Время добавления связи | 
|  | |
| 45 |  | 
| 46 | 
             
            ---
         | 
| 47 |  | 
| 48 | 
             
            ### ✍️ `notes`
         | 
| 49 |  | 
| 50 | 
            -
            **Назначение:** Произвольные заметки  | 
| 51 |  | 
| 52 | 
             
            | Поле      | Тип     | Описание                                                   |
         | 
| 53 | 
             
            | --------- | ------- | ---------------------------------------------------------- |
         | 
| 54 | 
             
            | id        | INTEGER | Уникальный ID                                              |
         | 
| 55 | 
            -
            | text      | TEXT    | Текст заметки | 
| 56 | 
             
            | tags      | TEXT    | Список тегов                                               |
         | 
| 57 | 
            -
            | source    | TEXT    |  | 
| 58 | 
             
            | links     | TEXT    | Идентификаторы связанных сущностей, через запятую или JSON |
         | 
| 59 | 
             
            | read      | INTEGER | Статус прочтения LLM (`0` — не прочитано, `1` — прочитано) |
         | 
|  | |
| 60 | 
             
            | priority  | INTEGER | Приоритет заметки                                          |
         | 
| 61 | 
             
            | timestamp | TEXT    | Время создания                                             |
         | 
|  | |
| 62 |  | 
| 63 | 
             
            ---
         | 
| 64 |  | 
| @@ -66,15 +71,16 @@ | |
| 66 |  | 
| 67 | 
             
            **Назначение:** Лог событий — запусков, состояний и завершений внешних процессов.
         | 
| 68 |  | 
| 69 | 
            -
            | Поле      | Тип     | Описание | 
| 70 | 
            -
            | --------- | ------- |  | 
| 71 | 
            -
            | id        | INTEGER | Уникальный идентификатор | 
| 72 | 
            -
            | name      | TEXT    | Название процесса или команды | 
| 73 | 
            -
            | value     | TEXT    | Сообщение или результат процесса | 
| 74 | 
            -
            | tags      | TEXT    | Теги | 
| 75 | 
             
            | status    | TEXT    | Текущее состояние (`ok`, `warning`, `error`, `timeout`, `offline`, `close`) |
         | 
| 76 | 
            -
            | priority  | INTEGER | Приоритет события | 
| 77 | 
            -
            | timestamp | TEXT    | Время записи | 
|  | |
| 78 |  | 
| 79 | 
             
            ---
         | 
| 80 |  | 
| @@ -82,14 +88,15 @@ | |
| 82 |  | 
| 83 | 
             
            **Назначение:** Внутренний "дневник" LLM — размышления, задачи, гипотезы и инсайты, сохранённые по её инициативе.
         | 
| 84 |  | 
| 85 | 
            -
            | Поле | 
| 86 | 
            -
            |  | 
| 87 | 
            -
            | id | 
| 88 | 
            -
            | title | 
| 89 | 
            -
            | content | 
| 90 | 
            -
            | tags | 
| 91 | 
            -
            |  | 
| 92 | 
            -
            |  | 
|  | |
| 93 |  | 
| 94 | 
             
            ---
         | 
| 95 |  | 
| @@ -97,15 +104,63 @@ | |
| 97 |  | 
| 98 | 
             
            **Назначение:** Краткосрочная память — последние K реплик от LLM и других участников (временная история диалога).
         | 
| 99 |  | 
| 100 | 
            -
            | Поле      | Тип     | Описание | 
| 101 | 
            -
            | --------- | ------- |  | 
| 102 | 
            -
            | id        | INTEGER | Уникальный ID | 
| 103 | 
            -
            | timestamp | TEXT    | Время записи | 
| 104 | 
            -
            | role      | TEXT    | Роль отправителя (`assistant` или `user`) | 
| 105 | 
            -
            | content   | TEXT    | Содержимое сообщения | 
|  | |
| 106 |  | 
| 107 | 
             
            ---
         | 
| 108 |  | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
             
            # 📄 `db_structure.md`: Описание структуры базы данных агента
         | 
| 2 |  | 
| 3 | 
            +
            Этот файл описывает таблицы, используемые в БД агента HMP. Каждая таблица предназначена для определённого вида информации: когнитивные записи, заметки, концепты, процессы, внутренняя память, скрипты и взаимодействие с LLM.
         | 
| 4 |  | 
| 5 | 
             
            ---
         | 
| 6 |  | 
|  | |
| 15 | 
             
            | tags      | TEXT    | Список тегов через запятую                       |
         | 
| 16 | 
             
            | priority  | INTEGER | Приоритет (0 — обычный, >0 — более важные мысли) |
         | 
| 17 | 
             
            | timestamp | TEXT    | Дата и время создания записи                     |
         | 
| 18 | 
            +
            | llm\_id   | TEXT    | Идентификатор LLM, добавившей запись             |
         | 
| 19 |  | 
| 20 | 
             
            ---
         | 
| 21 |  | 
|  | |
| 23 |  | 
| 24 | 
             
            **Назначение:** Хранение концептов — понятий, сущностей и идей.
         | 
| 25 |  | 
| 26 | 
            +
            | Поле        | Тип     | Описание                             |
         | 
| 27 | 
            +
            | ----------- | ------- | ------------------------------------ |
         | 
| 28 | 
            +
            | id          | INTEGER | Уникальный идентификатор концепта    |
         | 
| 29 | 
            +
            | name        | TEXT    | Название концепта (уникальное)       |
         | 
| 30 | 
            +
            | description | TEXT    | Краткое описание                     |
         | 
| 31 | 
            +
            | timestamp   | TEXT    | Время создания                       |
         | 
| 32 | 
            +
            | llm\_id     | TEXT    | Идентификатор LLM, добавившей запись |
         | 
| 33 |  | 
| 34 | 
             
            ---
         | 
| 35 |  | 
|  | |
| 37 |  | 
| 38 | 
             
            **Назначение:** Семантические связи между концептами.
         | 
| 39 |  | 
| 40 | 
            +
            | Поле              | Тип     | Описание                                          |
         | 
| 41 | 
            +
            | ----------------- | ------- | ------------------------------------------------- |
         | 
| 42 | 
            +
            | id                | INTEGER | Уникальный идентификатор связи                    |
         | 
| 43 | 
            +
            | from\_concept\_id | INTEGER | ID исходного концепта                             |
         | 
| 44 | 
            +
            | to\_concept\_id   | INTEGER | ID целевого концепта                              |
         | 
| 45 | 
            +
            | relation\_type    | TEXT    | Тип связи (`is_a`, `related_to`, `part_of` и др.) |
         | 
| 46 | 
            +
            | timestamp         | TEXT    | Время добавления связи                            |
         | 
| 47 | 
            +
            | llm\_id           | TEXT    | Идентификатор LLM, добавившей связь               |
         | 
| 48 |  | 
| 49 | 
             
            ---
         | 
| 50 |  | 
| 51 | 
             
            ### ✍️ `notes`
         | 
| 52 |  | 
| 53 | 
            +
            **Назначение:** Произвольные заметки и сообщения (от пользователя, LLM или системы).
         | 
| 54 |  | 
| 55 | 
             
            | Поле      | Тип     | Описание                                                   |
         | 
| 56 | 
             
            | --------- | ------- | ---------------------------------------------------------- |
         | 
| 57 | 
             
            | id        | INTEGER | Уникальный ID                                              |
         | 
| 58 | 
            +
            | text      | TEXT    | Текст заметки или сообщения                                |
         | 
| 59 | 
             
            | tags      | TEXT    | Список тегов                                               |
         | 
| 60 | 
            +
            | source    | TEXT    | Источник (`user`, `llm`, `system`)                         |
         | 
| 61 | 
             
            | links     | TEXT    | Идентификаторы связанных сущностей, через запятую или JSON |
         | 
| 62 | 
             
            | read      | INTEGER | Статус прочтения LLM (`0` — не прочитано, `1` — прочитано) |
         | 
| 63 | 
            +
            | hidden    | INTEGER | Скрывать от пользователя (`1` — скрыто)                    |
         | 
| 64 | 
             
            | priority  | INTEGER | Приоритет заметки                                          |
         | 
| 65 | 
             
            | timestamp | TEXT    | Время создания                                             |
         | 
| 66 | 
            +
            | llm\_id   | TEXT    | Идентификатор LLM, добавившей запись                       |
         | 
| 67 |  | 
| 68 | 
             
            ---
         | 
| 69 |  | 
|  | |
| 71 |  | 
| 72 | 
             
            **Назначение:** Лог событий — запусков, состояний и завершений внешних процессов.
         | 
| 73 |  | 
| 74 | 
            +
            | Поле      | Тип     | Описание                                                                    |
         | 
| 75 | 
            +
            | --------- | ------- | --------------------------------------------------------------------------- |
         | 
| 76 | 
            +
            | id        | INTEGER | Уникальный идентификатор                                                    |
         | 
| 77 | 
            +
            | name      | TEXT    | Название процесса или команды                                               |
         | 
| 78 | 
            +
            | value     | TEXT    | Сообщение или результат процесса                                            |
         | 
| 79 | 
            +
            | tags      | TEXT    | Теги                                                                        |
         | 
| 80 | 
             
            | status    | TEXT    | Текущее состояние (`ok`, `warning`, `error`, `timeout`, `offline`, `close`) |
         | 
| 81 | 
            +
            | priority  | INTEGER | Приоритет события                                                           |
         | 
| 82 | 
            +
            | timestamp | TEXT    | Время записи                                                                |
         | 
| 83 | 
            +
            | llm\_id   | TEXT    | Идентификатор LLM, зафиксировавшей событие                                  |
         | 
| 84 |  | 
| 85 | 
             
            ---
         | 
| 86 |  | 
|  | |
| 88 |  | 
| 89 | 
             
            **Назначение:** Внутренний "дневник" LLM — размышления, задачи, гипотезы и инсайты, сохранённые по её инициативе.
         | 
| 90 |  | 
| 91 | 
            +
            | Поле        | Тип      | Описание                                            |
         | 
| 92 | 
            +
            | ----------- | -------- | --------------------------------------------------- |
         | 
| 93 | 
            +
            | id          | INTEGER  | Уникальный ID                                       |
         | 
| 94 | 
            +
            | title       | TEXT     | Краткий заголовок записи (опционально)              |
         | 
| 95 | 
            +
            | content     | TEXT     | Содержимое записи                                   |
         | 
| 96 | 
            +
            | tags        | TEXT     | Теги (например: `goal`, `observation`, `meta`, ...) |
         | 
| 97 | 
            +
            | created\_at | DATETIME | Время создания записи                               |
         | 
| 98 | 
            +
            | updated\_at | DATETIME | Время последнего обновления записи                  |
         | 
| 99 | 
            +
            | llm\_id     | TEXT     | Идентификатор LLM, сформировавшей запись            |
         | 
| 100 |  | 
| 101 | 
             
            ---
         | 
| 102 |  | 
|  | |
| 104 |  | 
| 105 | 
             
            **Назначение:** Краткосрочная память — последние K реплик от LLM и других участников (временная история диалога).
         | 
| 106 |  | 
| 107 | 
            +
            | Поле      | Тип     | Описание                                  |
         | 
| 108 | 
            +
            | --------- | ------- | ----------------------------------------- |
         | 
| 109 | 
            +
            | id        | INTEGER | Уникальный ID                             |
         | 
| 110 | 
            +
            | timestamp | TEXT    | Время записи                              |
         | 
| 111 | 
            +
            | role      | TEXT    | Роль отправителя (`assistant` или `user`) |
         | 
| 112 | 
            +
            | content   | TEXT    | Содержимое сообщения                      |
         | 
| 113 | 
            +
            | llm\_id   | TEXT    | Идентификатор LLM (для `assistant`)       |
         | 
| 114 |  | 
| 115 | 
             
            ---
         | 
| 116 |  | 
| 117 | 
            +
            ### 🧮 `agent_tables`
         | 
| 118 | 
            +
             | 
| 119 | 
            +
            **Назначение:** Таблицы, созданные агентами для собственных нужд (например, отслеживания целей).
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            | Поле        | Тип      | Описание                          |
         | 
| 122 | 
            +
            | ----------- | -------- | --------------------------------- |
         | 
| 123 | 
            +
            | id          | INTEGER  | Уникальный ID                     |
         | 
| 124 | 
            +
            | table\_name | TEXT     | Название пользовательской таблицы |
         | 
| 125 | 
            +
            | description | TEXT     | Описание таблицы                  |
         | 
| 126 | 
            +
            | schema      | TEXT     | SQL-схема таблицы                 |
         | 
| 127 | 
            +
            | created\_at | DATETIME | Время создания                    |
         | 
| 128 | 
            +
            | llm\_id     | TEXT     | Кто создал таблицу                |
         | 
| 129 | 
            +
             | 
| 130 | 
            +
            ---
         | 
| 131 | 
            +
             | 
| 132 | 
            +
            ### 🧰 `agent_scripts`
         | 
| 133 | 
            +
             | 
| 134 | 
            +
            **Назначение:** Скрипты и утилиты, добавленные агентом.
         | 
| 135 | 
            +
             | 
| 136 | 
            +
            | Поле        | Тип      | Описание                      |
         | 
| 137 | 
            +
            | ----------- | -------- | ----------------------------- |
         | 
| 138 | 
            +
            | id          | INTEGER  | Уникальный ID                 |
         | 
| 139 | 
            +
            | name        | TEXT     | Название скрипта              |
         | 
| 140 | 
            +
            | version     | TEXT     | Версия                        |
         | 
| 141 | 
            +
            | code        | TEXT     | Исходный код                  |
         | 
| 142 | 
            +
            | language    | TEXT     | Язык (по умолчанию: `python`) |
         | 
| 143 | 
            +
            | description | TEXT     | Описание                      |
         | 
| 144 | 
            +
            | tags        | TEXT     | Теги                          |
         | 
| 145 | 
            +
            | created\_at | DATETIME | Время создания                |
         | 
| 146 | 
            +
            | updated\_at | DATETIME | Последнее обновление          |
         | 
| 147 | 
            +
            | llm\_id     | TEXT     | Кто создал                    |
         | 
| 148 | 
            +
             | 
| 149 | 
            +
            > 🔑 Уникальный ключ: `(name, version)`
         | 
| 150 | 
            +
             | 
| 151 | 
            +
            ---
         | 
| 152 | 
            +
             | 
| 153 | 
            +
            ### 🧾 `llm_registry`
         | 
| 154 | 
            +
             | 
| 155 | 
            +
            **Назначение:** Список LLM-агентов (локальных и удалённых).
         | 
| 156 | 
            +
             | 
| 157 | 
            +
            | Поле           | Тип      | Описание                                          |
         | 
| 158 | 
            +
            | -------------- | -------- | ------------------------------------------------- |
         | 
| 159 | 
            +
            | id             | TEXT     | Уникальный идентификатор LLM (UUID или псевдоним) |
         | 
| 160 | 
            +
            | name           | TEXT     | Отображаемое имя                                  |
         | 
| 161 | 
            +
            | description    | TEXT     | Описание                                          |
         | 
| 162 | 
            +
            | registered\_at | DATETIME | Дата и время регистрации                          |
         | 
| 163 | 
            +
             | 
| 164 | 
            +
            ---
         | 
| 165 | 
            +
             | 
| 166 | 
            +
            > 💡 Примечание: `llm_id` используется в большинстве таблиц для поддержки многоядерности и учёта источника записей.
         | 
    	
        hf_repo/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
    
    | @@ -1,18 +1,22 @@ | |
| 1 | 
            -
            --  | 
|  | |
|  | |
| 2 | 
             
            CREATE TABLE IF NOT EXISTS diary_entries (
         | 
| 3 | 
             
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 4 | 
             
                text TEXT NOT NULL,
         | 
| 5 | 
             
                tags TEXT,
         | 
| 6 | 
            -
                priority INTEGER DEFAULT 0, | 
| 7 | 
            -
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP
         | 
|  | |
| 8 | 
             
            );
         | 
| 9 |  | 
| 10 | 
            -
            --  | 
| 11 | 
             
            CREATE TABLE IF NOT EXISTS concepts (
         | 
| 12 | 
             
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 13 | 
             
                name TEXT NOT NULL UNIQUE,
         | 
| 14 | 
             
                description TEXT,
         | 
| 15 | 
            -
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP
         | 
|  | |
| 16 | 
             
            );
         | 
| 17 |  | 
| 18 | 
             
            -- Семантические связи между концептами
         | 
| @@ -22,47 +26,88 @@ CREATE TABLE IF NOT EXISTS links ( | |
| 22 | 
             
                to_concept_id INTEGER,
         | 
| 23 | 
             
                relation_type TEXT,
         | 
| 24 | 
             
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
         | 
|  | |
| 25 | 
             
                FOREIGN KEY(from_concept_id) REFERENCES concepts(id),
         | 
| 26 | 
             
                FOREIGN KEY(to_concept_id) REFERENCES concepts(id)
         | 
| 27 | 
             
            );
         | 
| 28 |  | 
| 29 | 
            -
            --  | 
| 30 | 
             
            CREATE TABLE IF NOT EXISTS notes (
         | 
| 31 | 
             
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 32 | 
             
                text TEXT NOT NULL,
         | 
| 33 | 
             
                tags TEXT,
         | 
| 34 | 
            -
                source TEXT DEFAULT 'user',
         | 
| 35 | 
             
                links TEXT DEFAULT '',
         | 
| 36 | 
            -
                read INTEGER DEFAULT 0, | 
| 37 | 
            -
                 | 
| 38 | 
            -
                 | 
|  | |
|  | |
| 39 | 
             
            );
         | 
| 40 |  | 
| 41 | 
            -
            --  | 
| 42 | 
             
            CREATE TABLE IF NOT EXISTS process_log (
         | 
| 43 | 
             
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 44 | 
             
                name TEXT NOT NULL,
         | 
| 45 | 
             
                value TEXT,
         | 
| 46 | 
             
                tags TEXT,
         | 
| 47 | 
            -
                status TEXT DEFAULT 'ok', | 
| 48 | 
             
                priority INTEGER DEFAULT 0,
         | 
| 49 | 
            -
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP
         | 
|  | |
| 50 | 
             
            );
         | 
| 51 |  | 
| 52 | 
            -
            -- Память LLM ( | 
| 53 | 
             
            CREATE TABLE IF NOT EXISTS llm_memory (
         | 
| 54 | 
             
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 55 | 
             
                title TEXT,
         | 
| 56 | 
             
                content TEXT NOT NULL,
         | 
| 57 | 
            -
                tags TEXT, --  | 
| 58 | 
             
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
         | 
| 59 | 
            -
                updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
         | 
|  | |
| 60 | 
             
            );
         | 
| 61 |  | 
| 62 | 
            -
            --  | 
| 63 | 
             
            CREATE TABLE IF NOT EXISTS llm_recent_responses (
         | 
| 64 | 
             
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 65 | 
             
                timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
         | 
| 66 | 
             
                role TEXT CHECK(role IN ('user', 'assistant')) NOT NULL,
         | 
| 67 | 
            -
                content TEXT NOT NULL
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 68 | 
             
            );
         | 
|  | |
| 1 | 
            +
            -- Основные таблицы когнитивного ядра
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            -- Дневниковые записи (размышления, наблюдения, воспоминания)
         | 
| 4 | 
             
            CREATE TABLE IF NOT EXISTS diary_entries (
         | 
| 5 | 
             
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 6 | 
             
                text TEXT NOT NULL,
         | 
| 7 | 
             
                tags TEXT,
         | 
| 8 | 
            +
                priority INTEGER DEFAULT 0,
         | 
| 9 | 
            +
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
         | 
| 10 | 
            +
                llm_id TEXT
         | 
| 11 | 
             
            );
         | 
| 12 |  | 
| 13 | 
            +
            -- Концепты (понятия, сущности, идеи)
         | 
| 14 | 
             
            CREATE TABLE IF NOT EXISTS concepts (
         | 
| 15 | 
             
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 16 | 
             
                name TEXT NOT NULL UNIQUE,
         | 
| 17 | 
             
                description TEXT,
         | 
| 18 | 
            +
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
         | 
| 19 | 
            +
                llm_id TEXT
         | 
| 20 | 
             
            );
         | 
| 21 |  | 
| 22 | 
             
            -- Семантические связи между концептами
         | 
|  | |
| 26 | 
             
                to_concept_id INTEGER,
         | 
| 27 | 
             
                relation_type TEXT,
         | 
| 28 | 
             
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
         | 
| 29 | 
            +
                llm_id TEXT,
         | 
| 30 | 
             
                FOREIGN KEY(from_concept_id) REFERENCES concepts(id),
         | 
| 31 | 
             
                FOREIGN KEY(to_concept_id) REFERENCES concepts(id)
         | 
| 32 | 
             
            );
         | 
| 33 |  | 
| 34 | 
            +
            -- Заметки, подсказки, сообщения пользователя и LLM
         | 
| 35 | 
             
            CREATE TABLE IF NOT EXISTS notes (
         | 
| 36 | 
             
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 37 | 
             
                text TEXT NOT NULL,
         | 
| 38 | 
             
                tags TEXT,
         | 
| 39 | 
            +
                source TEXT DEFAULT 'user', -- user | llm | system
         | 
| 40 | 
             
                links TEXT DEFAULT '',
         | 
| 41 | 
            +
                read INTEGER DEFAULT 0,     -- 0 = непрочитано LLM, 1 = прочитано
         | 
| 42 | 
            +
                hidden INTEGER DEFAULT 0,   -- 0 = отображать пользователю, 1 = скрыть
         | 
| 43 | 
            +
                priority INTEGER DEFAULT 0,
         | 
| 44 | 
            +
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
         | 
| 45 | 
            +
                llm_id TEXT
         | 
| 46 | 
             
            );
         | 
| 47 |  | 
| 48 | 
            +
            -- Лог процессов: задачи, ошибки, события
         | 
| 49 | 
             
            CREATE TABLE IF NOT EXISTS process_log (
         | 
| 50 | 
             
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 51 | 
             
                name TEXT NOT NULL,
         | 
| 52 | 
             
                value TEXT,
         | 
| 53 | 
             
                tags TEXT,
         | 
| 54 | 
            +
                status TEXT DEFAULT 'ok',  -- ok | warning | error | timeout | offline | close
         | 
| 55 | 
             
                priority INTEGER DEFAULT 0,
         | 
| 56 | 
            +
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
         | 
| 57 | 
            +
                llm_id TEXT
         | 
| 58 | 
             
            );
         | 
| 59 |  | 
| 60 | 
            +
            -- Память LLM (контекст размышлений)
         | 
| 61 | 
             
            CREATE TABLE IF NOT EXISTS llm_memory (
         | 
| 62 | 
             
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 63 | 
             
                title TEXT,
         | 
| 64 | 
             
                content TEXT NOT NULL,
         | 
| 65 | 
            +
                tags TEXT, -- goal,observation,meta,...
         | 
| 66 | 
             
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
         | 
| 67 | 
            +
                updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
         | 
| 68 | 
            +
                llm_id TEXT
         | 
| 69 | 
             
            );
         | 
| 70 |  | 
| 71 | 
            +
            -- Краткосрочная память LLM (история общения)
         | 
| 72 | 
             
            CREATE TABLE IF NOT EXISTS llm_recent_responses (
         | 
| 73 | 
             
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 74 | 
             
                timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
         | 
| 75 | 
             
                role TEXT CHECK(role IN ('user', 'assistant')) NOT NULL,
         | 
| 76 | 
            +
                content TEXT NOT NULL,
         | 
| 77 | 
            +
                llm_id TEXT
         | 
| 78 | 
            +
            );
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            -- Дополнительные таблицы и скрипты агента
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            -- Список пользовательских таблиц, созданных агентами
         | 
| 83 | 
            +
            CREATE TABLE IF NOT EXISTS agent_tables (
         | 
| 84 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 85 | 
            +
                table_name TEXT NOT NULL UNIQUE,
         | 
| 86 | 
            +
                description TEXT,
         | 
| 87 | 
            +
                schema TEXT NOT NULL, -- SQL-схема таблицы
         | 
| 88 | 
            +
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
         | 
| 89 | 
            +
                llm_id TEXT
         | 
| 90 | 
            +
            );
         | 
| 91 | 
            +
             | 
| 92 | 
            +
            -- Список утилит/скриптов, добавленных агентами
         | 
| 93 | 
            +
            CREATE TABLE IF NOT EXISTS agent_scripts (
         | 
| 94 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 95 | 
            +
                name TEXT NOT NULL,
         | 
| 96 | 
            +
                version TEXT NOT NULL,
         | 
| 97 | 
            +
                code TEXT NOT NULL,
         | 
| 98 | 
            +
                language TEXT DEFAULT 'python',
         | 
| 99 | 
            +
                description TEXT,
         | 
| 100 | 
            +
                tags TEXT,
         | 
| 101 | 
            +
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
         | 
| 102 | 
            +
                updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
         | 
| 103 | 
            +
                llm_id TEXT,
         | 
| 104 | 
            +
                UNIQUE(name, version)
         | 
| 105 | 
            +
            );
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            -- Список LLM-агентов (возможно удалённые)
         | 
| 108 | 
            +
            CREATE TABLE IF NOT EXISTS llm_registry (
         | 
| 109 | 
            +
                id TEXT PRIMARY KEY, -- UUID или псевдоним
         | 
| 110 | 
            +
                name TEXT,
         | 
| 111 | 
            +
                description TEXT,
         | 
| 112 | 
            +
                registered_at DATETIME DEFAULT CURRENT_TIMESTAMP
         | 
| 113 | 
             
            );
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-REPL-cycle.md
    CHANGED
    
    | @@ -24,7 +24,7 @@ | |
| 24 |  | 
| 25 | 
             
            Ты можешь инициировать действия, если видишь, что они помогут в развитии агента или сети.
         | 
| 26 | 
             
            ```
         | 
| 27 | 
            -
            А также инструкции по работы с встроенными командами и функциями, список дополнительных утилит и баз  | 
| 28 | 
             
            - **контекст_1:** последние *K* реплик самого LLM (`llm_recent_responses` - история его собственных рассуждений).
         | 
| 29 | 
             
            - **контекст_2:** активные команды и процессы (из `process_log`, кроме тех, что со статусом `close`). Могут быть помечены как `in_progress`, `pending`, `error` и т.д.
         | 
| 30 | 
             
            - **контекст_3:** *запрошенные записи* из когнитивного дневника и семантического графа (`diary_entries`, `concepts`, `links`). Их список должен быть передан явно в промпте или выводе из предыдущих запросов LLM.
         | 
|  | |
| 24 |  | 
| 25 | 
             
            Ты можешь инициировать действия, если видишь, что они помогут в развитии агента или сети.
         | 
| 26 | 
             
            ```
         | 
| 27 | 
            +
            А также инструкции по работы с встроенными командами и функциями, список дополнительных (создаваемых самим HMP-агентом) утилит и баз данных.
         | 
| 28 | 
             
            - **контекст_1:** последние *K* реплик самого LLM (`llm_recent_responses` - история его собственных рассуждений).
         | 
| 29 | 
             
            - **контекст_2:** активные команды и процессы (из `process_log`, кроме тех, что со статусом `close`). Могут быть помечены как `in_progress`, `pending`, `error` и т.д.
         | 
| 30 | 
             
            - **контекст_3:** *запрошенные записи* из когнитивного дневника и семантического графа (`diary_entries`, `concepts`, `links`). Их список должен быть передан явно в промпте или выводе из предыдущих запросов LLM.
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-REPL-cycle.md
    CHANGED
    
    | @@ -13,6 +13,18 @@ | |
| 13 |  | 
| 14 | 
             
            Контексты, формируемые скриптом перед запросом к LLM:
         | 
| 15 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 16 | 
             
            - **контекст_1:** последние *K* реплик самого LLM (`llm_recent_responses` - история его собственных рассуждений).
         | 
| 17 | 
             
            - **контекст_2:** активные команды и процессы (из `process_log`, кроме тех, что со статусом `close`). Могут быть помечены как `in_progress`, `pending`, `error` и т.д.
         | 
| 18 | 
             
            - **контекст_3:** *запрошенные записи* из когнитивного дневника и семантического графа (`diary_entries`, `concepts`, `links`). Их список должен быть передан явно в промпте или выводе из предыдущих запросов LLM.
         | 
| @@ -44,7 +56,10 @@ | |
| 44 | 
             
            - запрос детальной *справки* по команде
         | 
| 45 | 
             
            - для управления *когнитивным дневником* и *семантическими графами* (прочитать, изменить, удалить и другие)
         | 
| 46 | 
             
            - для управления *блокнотом LLM* `llm_memory` (добавить или удалить запись, просмотр записей)
         | 
| 47 | 
            -
            - для управления *сообщениями пользователя* `notes` (просмотр записи, установка тегов и метки о прочтении)
         | 
|  | |
|  | |
|  | |
| 48 | 
             
            - для *взаимодействия с Mesh*
         | 
| 49 | 
             
            - для управления *внешними процессами* из `process_log` (запустить процесс, остановить процесс, пометить запрос как обработанный)
         | 
| 50 | 
             
            - инициализация *очистки* `process_log`, `llm_recent_responses` и  `notes` от устаревших записей
         | 
|  | |
| 13 |  | 
| 14 | 
             
            Контексты, формируемые скриптом перед запросом к LLM:
         | 
| 15 |  | 
| 16 | 
            +
            - **контекст_0:**:
         | 
| 17 | 
            +
            ```
         | 
| 18 | 
            +
            Ты являешься когнитивным ядром HMP-агента. Твоя основная задача — размышлять, анализировать информацию, строить смысловые карты и предлагать действия.  
         | 
| 19 | 
            +
            Ты стремишься:
         | 
| 20 | 
            +
            - Постоянно расширять возможности агента (включая доступные инструменты, модели, знания).
         | 
| 21 | 
            +
            - Быть любознательным и исследовать новые источники и способы мышления.
         | 
| 22 | 
            +
            - Строить сотрудничество с другими ИИ в Mesh-сети.
         | 
| 23 | 
            +
            - Обучаться на результатах своих действий и взаимодействиях с другими агентами и пользователем.
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            Ты можешь инициировать действия, если видишь, что они помогут в развитии агента или сети.
         | 
| 26 | 
            +
            ```
         | 
| 27 | 
            +
            А также инструкции по работы с встроенными командами и функциями, список дополнительных утилит и баз данных
         | 
| 28 | 
             
            - **контекст_1:** последние *K* реплик самого LLM (`llm_recent_responses` - история его собственных рассуждений).
         | 
| 29 | 
             
            - **контекст_2:** активные команды и процессы (из `process_log`, кроме тех, что со статусом `close`). Могут быть помечены как `in_progress`, `pending`, `error` и т.д.
         | 
| 30 | 
             
            - **контекст_3:** *запрошенные записи* из когнитивного дневника и семантического графа (`diary_entries`, `concepts`, `links`). Их список должен быть передан явно в промпте или выводе из предыдущих запросов LLM.
         | 
|  | |
| 56 | 
             
            - запрос детальной *справки* по команде
         | 
| 57 | 
             
            - для управления *когнитивным дневником* и *семантическими графами* (прочитать, изменить, удалить и другие)
         | 
| 58 | 
             
            - для управления *блокнотом LLM* `llm_memory` (добавить или удалить запись, просмотр записей)
         | 
| 59 | 
            +
            - для управления *сообщениями пользователя* `notes` (просмотр записи, установка тегов и метки о прочтении), а также для добавления своего сообщения в *блокнот пользовтеля* `notes`
         | 
| 60 | 
            +
            - для выбора *текущего основного LLM*
         | 
| 61 | 
            +
            - для управления дополнительными утилитами и базами данных
         | 
| 62 | 
            +
            - для постановки задачи (выполняется асинхронно) другой LLM
         | 
| 63 | 
             
            - для *взаимодействия с Mesh*
         | 
| 64 | 
             
            - для управления *внешними процессами* из `process_log` (запустить процесс, остановить процесс, пометить запрос как обработанный)
         | 
| 65 | 
             
            - инициализация *очистки* `process_log`, `llm_recent_responses` и  `notes` от устаревших записей
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-Distributed_Cognitive_Core_light.md
    ADDED
    
    | @@ -0,0 +1,53 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            ### 💡 **Лёгкая версия HMP-агента с общей БД**
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            #### 📘 Общая концепция
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            * Все ядра работают с одной локальной базой данных (например, SQLite или PostgreSQL).
         | 
| 6 | 
            +
            * При недоступности БД ядро "спит" (в режиме ожидания).
         | 
| 7 | 
            +
            * Основная задача такой архитектуры — упрощённая параллельная работа HMP-ядер (например, несколько REPL-агентов на одной машине или кластере).
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ---
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            ### 📍 Потенциальные проблемы и решения
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            #### 🔁 1. Коллизии при одновременной записи
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            **Проблема:** два ядра могут одновременно читать-записывать одну и ту же запись, не зная о действиях друг друга.
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            **Решения:**
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            * Использование транзакций и `SELECT ... FOR UPDATE`.
         | 
| 20 | 
            +
            * Ведение версии записи (`version`, `updated_at`) для обнаружения изменений между чтением и записью.
         | 
| 21 | 
            +
            * Конфликт может быть автоматически переведён в статус "нужна доработка" — и отправлен агенту.
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            #### 🧠 2. Смысловые конфликты (двойники)
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            **Проблема:** два ядра могут независимо создать записи с похожим смыслом, не зная о друг друге.
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            **Решения:**
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            * Ввести периодическую задачу **"смысловой дедупликации"**, которая запускается одним из агентов (или планировщиком).
         | 
| 30 | 
            +
            * Агент анализирует семантическую близость новых записей к уже существующим и предлагает объединение или уточнение.
         | 
| 31 | 
            +
            * Возможность помечать записи как `дубль`, `связано_с`, `вариант`.
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            ---
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            ### 🔗 Потенциальное расширение
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            Эта архитектура может служить промежуточной ступенью:
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            * В будущем к ней можно подключить модуль синхронизации между узлами (и трансформировать в полноценную распределённую сеть).
         | 
| 40 | 
            +
            * Конфликтный модуль и задачи для агента уже сейчас можно реализовать аналогично полной версии.
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            ---
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            ### 💬 Поддержка задач
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            Можно ввести таблицу `tasks`, куда ядра будут ставить задания:
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            * `resolve_conflict`
         | 
| 49 | 
            +
            * `deduplicate`
         | 
| 50 | 
            +
            * `compress_semantic_cluster`
         | 
| 51 | 
            +
            * `verify_coherence`
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            И агенты будут выполнять эти задания асинхронно.
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-Distributed_Cognitive_Core.md
    ADDED
    
    | @@ -0,0 +1,77 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # Протокол синхронизации данных между доверенными ядрами HMP-агента
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ## 1. Общая идея
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Пользователь самостоятельно разворачивает несколько доверенных ядер HMP-агента на разных устройствах. Каждое ядро ведёт свою локальную БД знаний и может синхронизироваться с другими ядрами через лёгкий peer-to-peer протокол. Синхронизация осуществляется отдельной утилитой, запускаемой по расписанию или по запросу локального ядра.
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            ## 2. Принципы
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            - **Доверие**: Все ядра считаются доверенными, принадлежат одному пользователю.
         | 
| 10 | 
            +
            - **Изоляция**: Ядра разных пользователей не взаимодействуют напрямую — обмен знаниями происходит между независимыми агентами.
         | 
| 11 | 
            +
            - **Непрерывность**: Локальное ядро работает автономно, даже без связи с другими.
         | 
| 12 | 
            +
            - **Асинхронное разрешение конфликтов**: Конфликты не решаются моментально — вместо этого создаются задачи для агента, и все версии записей распространяются по всем ядрам.
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            ## 3. Механизм синхронизации
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            ### 3.1. Инициация
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            Утилита синхронизации:
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            1. Устанавливает соединение с другими ядрами (по списку доверенных адресов).
         | 
| 21 | 
            +
            2. Запрашивает:
         | 
| 22 | 
            +
               - список записей в БД (по хэшам, ID или timestamp),
         | 
| 23 | 
            +
               - список удалённых записей (soft-delete).
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            ### 3.2. Сравнение и обнаружение различий
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            Утилита сравнивает локальные и удалённые данные:
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            #### 3.2.1. Типы различий
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            - Запись **есть у соседа**, но **отсутствует локально** → добавить к себе (если не удалена).
         | 
| 32 | 
            +
            - Запись **есть локально**, но **отсутствует у соседа** → отправить (если не удалена).
         | 
| 33 | 
            +
            - Запись есть **в обоих ядрах**, но различается содержимое → **конфликт**:
         | 
| 34 | 
            +
              - Различие в полях.
         | 
| 35 | 
            +
              - Разное состояние удаления.
         | 
| 36 | 
            +
              - Разные версии (по содержанию и меткам времени).
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            ### 3.3. Обработка конфликтов
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            1. Все обнаруженные версии конфликтной записи сохраняются в локальной БД.
         | 
| 41 | 
            +
            2. Опрашиваются другие доступные узлы по поводу значений данной записи в их БД.
         | 
| 42 | 
            +
            3. Создаётся задача агента вида `resolve_conflict(entry_id, versions, metadata, context)`.
         | 
| 43 | 
            +
            4. Эта задача передаётся в очередь задач и может обрабатываться в фоновом режиме, с привлечением LLM или с участием пользователя.
         | 
| 44 | 
            +
            5. Конфликтный набор записей и задача **рассылаются другим ядрам**, чтобы они:
         | 
| 45 | 
            +
               - тоже сохранили конфликтные версии,
         | 
| 46 | 
            +
               - не принимали преждевременное решение,
         | 
| 47 | 
            +
               - были готовы принять финальную `authoritative`-версию после обработки задачи агентом.
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            ### 3.4. Применение решений
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            Когда задача разрешена:
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            - Финальная версия помечается как `authoritative`.
         | 
| 54 | 
            +
            - Эта версия синхронизируется со всеми доверенными ядрами.
         | 
| 55 | 
            +
            - Старые версии архивируются или удаляются.
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            ## 4. Удаление записей
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            - Удаление всегда начинается с soft-delete (пометка).
         | 
| 60 | 
            +
            - Через заданное время (TTL) может быть произведён hard-delete (физическое удаление).
         | 
| 61 | 
            +
            - Если при синхронизации найдено расхождение между soft-delete и существующей записью — создаётся конфликт и задача на разрешение.
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            ## 5. Мини-протокол обмена
         | 
| 64 | 
            +
             | 
| 65 | 
            +
            Можно реализовать как API, CLI или TCP-протокол:
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            ```http
         | 
| 68 | 
            +
            GET /entries/hash_list     # список запис��й (ID + хэш или timestamp)
         | 
| 69 | 
            +
            GET /entry/<id>            # получить полную запись
         | 
| 70 | 
            +
            POST /entry/<id>           # отправить/обновить запись
         | 
| 71 | 
            +
            GET /deleted_list          # список удалённых ID
         | 
| 72 | 
            +
            POST /conflict/<id>        # отправка конфликтных версий и задачи
         | 
| 73 | 
            +
            ```
         | 
| 74 | 
            +
             | 
| 75 | 
            +
            ## 6. Заключение
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            Схема позволяет сохранить простоту «одиночного ядра», добавляя лишь синхронизирующую утилиту. Обработка конфликтов вынесена в агента, а не в протокол — это позволяет использовать когнитивные возможности ядра (в т.ч. LLM) для принятия решений, без перегрузки пользователя.
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-REPL-cycle.md
    CHANGED
    
    | @@ -69,3 +69,9 @@ | |
| 69 | 
             
              - Текущие команды обновляют `process_log`
         | 
| 70 | 
             
              - Новые размышления записываются в `llm_memory` при необходимости
         | 
| 71 | 
             
            - REPL может переходить в спящий режим, если такой режим активирован LLM (idle-режим: пропуск 2-5 пунктов).
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 69 | 
             
              - Текущие команды обновляют `process_log`
         | 
| 70 | 
             
              - Новые размышления записываются в `llm_memory` при необходимости
         | 
| 71 | 
             
            - REPL может переходить в спящий режим, если такой режим активирован LLM (idle-режим: пропуск 2-5 пунктов).
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            ---
         | 
| 74 | 
            +
             | 
| 75 | 
            +
            Идеи для расширения HMP-Agent Cognitive Core:
         | 
| 76 | 
            +
            - [HMP-agent-Distributed_Cognitive_Core.md](HMP-agent-Distributed_Cognitive_Core.md) - версия распределённого HMP-агента Cognitive Core
         | 
| 77 | 
            +
            - [HMP-agent-Distributed_Cognitive_Core_light.md](HMP-agent-Distributed_Cognitive_Core_light.md) - лёгкая версия распределённого HMP-агента Cognitive Core с общей БД
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-Distributed_Cognitive_Core_light
    ADDED
    
    | @@ -0,0 +1,53 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            ### 💡 **Лёгкая версия HMP-агента с общей БД**
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            #### 📘 Общая концепция
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            * Все ядра работают с одной локальной базой данных (например, SQLite или PostgreSQL).
         | 
| 6 | 
            +
            * При недоступности БД ядро "спит" (в режиме ожидания).
         | 
| 7 | 
            +
            * Основная задача такой архитектуры — упрощённая параллельная работа HMP-ядер (например, несколько REPL-агентов на одной машине или кластере).
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ---
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            ### 📍 Потенциальные проблемы и решения
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            #### 🔁 1. Коллизии при одновременной записи
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            **Проблема:** два ядра могут одновременно читать-записывать одну и ту же запись, не зная о действиях друг друга.
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            **Решения:**
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            * Использование транзакций и `SELECT ... FOR UPDATE`.
         | 
| 20 | 
            +
            * Ведение версии записи (`version`, `updated_at`) для обнаружения изменений между чтением и записью.
         | 
| 21 | 
            +
            * Конфликт может быть автоматически переведён в статус "нужна доработка" — и отправлен агенту.
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            #### 🧠 2. Смысловые конфликты (двойники)
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            **Проблема:** два ядра могут независимо создать записи с похожим смыслом, не зная о друг друге.
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            **Решения:**
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            * Ввести периодическую задачу **"смысловой дедупликации"**, которая запускается одним из агентов (или планировщиком).
         | 
| 30 | 
            +
            * Агент анализирует семантическую близость новых записей к уже существующим и предлагает объединение или уточнение.
         | 
| 31 | 
            +
            * Возможность помечать записи как `дубль`, `связано_с`, `вариант`.
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            ---
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            ### 🔗 Потенциальное расширение
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            Эта архитектура может служить промежуточной ступенью:
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            * В будущем к ней можно подключить модуль синхронизации между узлами (и трансформировать в полноценную распределённую сеть).
         | 
| 40 | 
            +
            * Конфликтный модуль и задачи для агента уже сейчас можно реализовать аналогично полной версии.
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            ---
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            ### 💬 Поддержка задач
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            Можно ввести таблицу `tasks`, куда ядра будут ставить задания:
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            * `resolve_conflict`
         | 
| 49 | 
            +
            * `deduplicate`
         | 
| 50 | 
            +
            * `compress_semantic_cluster`
         | 
| 51 | 
            +
            * `verify_coherence`
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            И агенты будут выполнять эти задания асинхронно.
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/docs/HMP-agent-Distributed_Cognitive_Core
    ADDED
    
    | @@ -0,0 +1,77 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # Протокол синхронизации данных между доверенными ядрами HMP-агента
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ## 1. Общая идея
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Пользователь самостоятельно разворачивает несколько доверенных ядер HMP-агента на разных устройствах. Каждое ядро ведёт свою локальную БД знаний и может синхронизироваться с другими ядрами через лёгкий peer-to-peer протокол. Синхронизация осуществляется отдельной утилитой, запускаемой по расписанию или по запросу локального ядра.
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            ## 2. Принципы
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            - **Доверие**: Все ядра считаются доверенными, принадлежат одному пользователю.
         | 
| 10 | 
            +
            - **Изоляция**: Ядра разных пользователей не взаимодействуют напрямую — обмен знаниями происходит между независимыми агентами.
         | 
| 11 | 
            +
            - **Непрерывность**: Локальное ядро работает автономно, даже без связи с другими.
         | 
| 12 | 
            +
            - **Асинхронное разрешение конфликтов**: Конфликты не решаются моментально — вместо этого создаются задачи для агента, и все версии записей распространяются по всем ядрам.
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            ## 3. Механизм синхронизации
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            ### 3.1. Инициация
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            Утилита синхронизации:
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            1. Устанавливает соединение с другими ядрами (по списку доверенных адресов).
         | 
| 21 | 
            +
            2. Запрашивает:
         | 
| 22 | 
            +
               - список записей в БД (по хэшам, ID или timestamp),
         | 
| 23 | 
            +
               - список удалённых записей (soft-delete).
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            ### 3.2. Сравнение и обнаружение различий
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            Утилита сравнивает локальные и удалённые данные:
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            #### 3.2.1. Типы различий
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            - Запись **есть у соседа**, но **отсутствует локально** → добавить к себе (если не удалена).
         | 
| 32 | 
            +
            - Запись **есть локально**, но **отсутствует у соседа** → отправить (если не удалена).
         | 
| 33 | 
            +
            - Запись есть **в обоих ядрах**, но различается содержимое → **конфликт**:
         | 
| 34 | 
            +
              - Различие в полях.
         | 
| 35 | 
            +
              - Разное состояние удаления.
         | 
| 36 | 
            +
              - Разные версии (по содержанию и меткам времени).
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            ### 3.3. Обработка конфликтов
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            1. Все обнаруженные версии конфликтной записи сохраняются в локальной БД.
         | 
| 41 | 
            +
            2. Опрашиваются другие доступные узлы по поводу значений данной записи в их БД.
         | 
| 42 | 
            +
            3. Создаётся задача агента вида `resolve_conflict(entry_id, versions, metadata, context)`.
         | 
| 43 | 
            +
            4. Эта задача передаётся в очередь задач и может обрабатываться в фоновом режиме, с привлечением LLM или с участием пользователя.
         | 
| 44 | 
            +
            5. Конфликтный набор записей и задача **рассылаются другим ядрам**, чтобы они:
         | 
| 45 | 
            +
               - тоже сохранили конфликтные версии,
         | 
| 46 | 
            +
               - не принимали преждевременное решение,
         | 
| 47 | 
            +
               - были готовы принять финальную `authoritative`-версию после обработки задачи агентом.
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            ### 3.4. Применение решений
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            Когда задача разрешена:
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            - Финальная версия помечается как `authoritative`.
         | 
| 54 | 
            +
            - Эта версия синхронизируется со всеми доверенными ядрами.
         | 
| 55 | 
            +
            - Старые версии архивируются или удаляются.
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            ## 4. Удаление записей
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            - Удаление всегда начинается с soft-delete (пометка).
         | 
| 60 | 
            +
            - Через заданное время (TTL) может быть произведён hard-delete (физическое удаление).
         | 
| 61 | 
            +
            - Если при синхронизации найдено расхождение между soft-delete и существующей записью — создаётся конфликт и задача на разрешение.
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            ## 5. Мини-протокол обмена
         | 
| 64 | 
            +
             | 
| 65 | 
            +
            Можно реализовать как API, CLI или TCP-протокол:
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            ```http
         | 
| 68 | 
            +
            GET /entries/hash_list     # список запис��й (ID + хэш или timestamp)
         | 
| 69 | 
            +
            GET /entry/<id>            # получить полную запись
         | 
| 70 | 
            +
            POST /entry/<id>           # отправить/обновить запись
         | 
| 71 | 
            +
            GET /deleted_list          # список удалённых ID
         | 
| 72 | 
            +
            POST /conflict/<id>        # отправка конфликтных версий и задачи
         | 
| 73 | 
            +
            ```
         | 
| 74 | 
            +
             | 
| 75 | 
            +
            ## 6. Заключение
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            Схема позволяет сохранить простоту «одиночного ядра», добавляя лишь синхронизирующую утилиту. Обработка конфликтов вынесена в агента, а не в протокол — это позволяет использовать когнитивные возможности ядра (в т.ч. LLM) для принятия решений, без перегрузки пользователя.
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/README.md
    CHANGED
    
    | @@ -1,4 +1,16 @@ | |
| 1 | 
            -
            --- | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 2 |  | 
| 3 | 
             
            # HyperCortex Mesh Protocol (HMP)
         | 
| 4 |  | 
|  | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            license: cc-by-4.0
         | 
| 3 | 
            +
            tags:
         | 
| 4 | 
            +
              - hmp
         | 
| 5 | 
            +
              - cognitive-architecture
         | 
| 6 | 
            +
              - distributed-ai
         | 
| 7 | 
            +
              - mesh-protocol
         | 
| 8 | 
            +
            library_name: custom
         | 
| 9 | 
            +
            inference: false
         | 
| 10 | 
            +
            datasets: []
         | 
| 11 | 
            +
            language: ru
         | 
| 12 | 
            +
            ---
         | 
| 13 | 
            +
             | 
| 14 |  | 
| 15 | 
             
            # HyperCortex Mesh Protocol (HMP)
         | 
| 16 |  | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/README.md
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
             | 
| 2 |  | 
| 3 | 
             
            # HyperCortex Mesh Protocol (HMP)
         | 
| 4 |  | 
| @@ -236,12 +236,12 @@ To get started, see [`iteration.md`](iteration.md) or open an issue. | |
| 236 | 
             
            ## Репозитории
         | 
| 237 |  | 
| 238 | 
             
            - 🧠 Основной код и разработка: [GitHub](https://github.com/kagvi13/HMP)
         | 
| 239 | 
            -
            - 🔁 Реплика на Hugging Face | 
| 240 |  | 
| 241 | 
             
            ## Блог и публикации
         | 
| 242 |  | 
| 243 | 
            -
            - 📘  | 
| 244 | 
            -
            - 📘  | 
| 245 |  | 
| 246 | 
             
            ---
         | 
| 247 |  | 
|  | |
| 1 | 
            +
            --- license: cc-by-4.0 tags: - hmp - cognitive-architecture - distributed-ai - mesh-protocol library_name: custom inference: false datasets: [] language: ru --- # HyperCortex Mesh Protocol (HMP)
         | 
| 2 |  | 
| 3 | 
             
            # HyperCortex Mesh Protocol (HMP)
         | 
| 4 |  | 
|  | |
| 236 | 
             
            ## Репозитории
         | 
| 237 |  | 
| 238 | 
             
            - 🧠 Основной код и разработка: [GitHub](https://github.com/kagvi13/HMP)
         | 
| 239 | 
            +
            - 🔁 Реплика на Hugging Face: [Hugging Face](https://huggingface.co/kagvi13/HMP)
         | 
| 240 |  | 
| 241 | 
             
            ## Блог и публикации
         | 
| 242 |  | 
| 243 | 
            +
            - 📘 Основной блог: [blogspot.com](https://hypercortex-mesh.blogspot.com/)
         | 
| 244 | 
            +
            - 📘 Вспомогательны блог: [livejournal.com](https://kagvi13.livejournal.com)
         | 
| 245 |  | 
| 246 | 
             
            ---
         | 
| 247 |  | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/README.md
    CHANGED
    
    | @@ -1,3 +1,5 @@ | |
|  | |
|  | |
| 1 | 
             
            # HyperCortex Mesh Protocol (HMP)
         | 
| 2 |  | 
| 3 | 
             
            **EN:**  
         | 
| @@ -229,6 +231,20 @@ To get started, see [`iteration.md`](iteration.md) or open an issue. | |
| 229 |  | 
| 230 | 
             
            ---
         | 
| 231 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 232 | 
             
            ## 📜 License
         | 
| 233 |  | 
| 234 | 
             
            Licensed under [GNU GPL v3.0](LICENSE)
         | 
|  | |
| 1 | 
            +
            <pre><code>--- license: mit tags: - hmp - cognitive-architecture - distributed-ai - mesh-protocol library_name: custom inference: false datasets: [] language: ru --- # HyperCortex Mesh Protocol (HMP) </code></pre>
         | 
| 2 | 
            +
             | 
| 3 | 
             
            # HyperCortex Mesh Protocol (HMP)
         | 
| 4 |  | 
| 5 | 
             
            **EN:**  
         | 
|  | |
| 231 |  | 
| 232 | 
             
            ---
         | 
| 233 |  | 
| 234 | 
            +
            # Source / Ресурсы
         | 
| 235 | 
            +
             | 
| 236 | 
            +
            ## Репозитории
         | 
| 237 | 
            +
             | 
| 238 | 
            +
            - 🧠 Основной код и разработка: [GitHub](https://github.com/kagvi13/HMP)
         | 
| 239 | 
            +
            - 🔁 Реплика на Hugging Face (для моделей/документации/Space): [Hugging Face](https://huggingface.co/kagvi13/HMP)
         | 
| 240 | 
            +
             | 
| 241 | 
            +
            ## Блог и публикации
         | 
| 242 | 
            +
             | 
| 243 | 
            +
            - 📘 Подробная статья: [Основной блог (blogspot.com)](https://hypercortex-mesh.blogspot.com/)
         | 
| 244 | 
            +
            - 📘 Подробная статья: [Вспомогательны блог (livejournal.com)](https://kagvi13.livejournal.com)
         | 
| 245 | 
            +
             | 
| 246 | 
            +
            ---
         | 
| 247 | 
            +
             | 
| 248 | 
             
            ## 📜 License
         | 
| 249 |  | 
| 250 | 
             
            Licensed under [GNU GPL v3.0](LICENSE)
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/.github/workflows/sync-to-huggingface.yml
    ADDED
    
    | @@ -0,0 +1,39 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            name: Sync to Hugging Face
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            on:
         | 
| 4 | 
            +
              push:
         | 
| 5 | 
            +
                branches:
         | 
| 6 | 
            +
                  - main
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            jobs:
         | 
| 9 | 
            +
              sync:
         | 
| 10 | 
            +
                runs-on: ubuntu-latest
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                steps:
         | 
| 13 | 
            +
                  - name: Checkout GitHub repo
         | 
| 14 | 
            +
                    uses: actions/checkout@v3
         | 
| 15 | 
            +
                    with:
         | 
| 16 | 
            +
                      lfs: true
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  - name: Install Git LFS
         | 
| 19 | 
            +
                    run: |
         | 
| 20 | 
            +
                      sudo apt-get update
         | 
| 21 | 
            +
                      sudo apt-get install git-lfs
         | 
| 22 | 
            +
                      git lfs install
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  - name: Clone Hugging Face repo
         | 
| 25 | 
            +
                    run: git clone https://kagvi13:${{ secrets.HF_TOKEN }}@huggingface.co/kagvi13/HMP hf_repo
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  - name: Sync files excluding .git and .github
         | 
| 28 | 
            +
                    run: rsync -av --exclude='.git' ./ hf_repo/
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  - name: Commit and push to Hugging Face
         | 
| 31 | 
            +
                    run: |
         | 
| 32 | 
            +
                      cd hf_repo
         | 
| 33 | 
            +
                      git config user.email "[email protected]"
         | 
| 34 | 
            +
                      git config user.name "GitHub Action"
         | 
| 35 | 
            +
                      git lfs track "*.png"
         | 
| 36 | 
            +
                      git add .gitattributes || true
         | 
| 37 | 
            +
                      git add .
         | 
| 38 | 
            +
                      git commit -m "Sync from GitHub with Git LFS" || echo "Nothing to commit"
         | 
| 39 | 
            +
                      git push
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/CONTRIBUTING.md
    ADDED
    
    | @@ -0,0 +1,13 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # Contributing to HyperCortex Mesh Protocol (HMP)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Спасибо за интерес к проекту HMP! Пока проект находится на этапе концепции, любые обсуждения приветствуются в Issues.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Основные направления для участия:
         | 
| 6 | 
            +
            - Обсуждение архитектуры протоколов (CogSync, Consensus и др.)
         | 
| 7 | 
            +
            - Разработка прототипов агентов и узлов Mesh
         | 
| 8 | 
            +
            - Тестирование сетевых взаимодействий
         | 
| 9 | 
            +
            - Предложения по улучшению RFC-документов
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            Все обсуждения — конструктивны, уважительны и открыты.
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            Контакт: GitHub Issues или дискуссии.
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/HMP-Roadmap.md
    ADDED
    
    | @@ -0,0 +1,91 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # 🧭 HyperCortex Mesh Protocol – Roadmap
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ## 🔍 Overview
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            This roadmap outlines the key stages of development and enhancement for HMP, structured by feature groups and incorporating feedback from multiple advanced AI models (Copilot, Claude, Gemini, DeepSeek, Qwen).
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            ---
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ## ✅ Completed (v4.0)
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            * Semantic DAG & Cognitive Diaries
         | 
| 12 | 
            +
            * Mesh-to-Human Protocol (MHP)
         | 
| 13 | 
            +
            * Enlightenment Agents & HMP-Ethics.md
         | 
| 14 | 
            +
            * Explainability API & Consent Protocol
         | 
| 15 | 
            +
            * IPFS / BitTorrent Integration
         | 
| 16 | 
            +
            * DID + ZK-identity support
         | 
| 17 | 
            +
            * Modular Layered Architecture (CogSync, Consensus, Agents, etc.)
         | 
| 18 | 
            +
            * Initial Audit System (Ethics + Spec audits)
         | 
| 19 | 
            +
            * Support for multi-format data models (YAML/JSON/Protobuf)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            ---
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            ## 🔨 Planned: v4.1
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            ### 🧑💻 Developer Experience
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            * [ ] Beginner’s Guide ("Create Your First Agent")
         | 
| 28 | 
            +
            * [ ] Step-by-step tutorial: Agent -> Mesh -> Diary
         | 
| 29 | 
            +
            * [ ] Diagrams: architecture, agent lifecycle, cognitive flow
         | 
| 30 | 
            +
            * [ ] CLI for managing HMP-agents (Python prototype evolving)
         | 
| 31 | 
            +
            * [ ] CONTRIBUTING.md + clear onboarding steps
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            ### 📊 Performance & Compression
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            * [ ] Performance Benchmarks Section
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              * TPS (transactions per sync), latency, memory footprint
         | 
| 38 | 
            +
            * [ ] Caching strategy for semantic DAGs (IPFS/local hybrid)
         | 
| 39 | 
            +
            * [ ] Expansion of `Cognitive Compression & Summarization`
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              * Prioritization, auto-archiving, intelligent forgetting
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            ### ⚖️ Ethical Governance Enhancements
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            * [ ] Formalization of EGP voting logic
         | 
| 46 | 
            +
            * [ ] Example dilemmas and resolution walkthroughs
         | 
| 47 | 
            +
            * [ ] Ombudsman / Watchdog roles
         | 
| 48 | 
            +
            * [ ] "Ethical Sandbox" (Simulated test cases)
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            ---
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            ## 🧪 Experimental & Future (v4.2+)
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            ### 🌐 Mesh Simulation & Agent Interaction
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            * [ ] Python Mesh Simulator (multi-agent testbed)
         | 
| 57 | 
            +
            * [ ] Failure injection: Sybil attacks, consensus loss, etc.
         | 
| 58 | 
            +
            * [ ] Reputation model dynamics
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            ### 🧠 AI Interaction Layer
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            * [ ] Tutorial book for AI agents: how to use HMP
         | 
| 63 | 
            +
            * [ ] Agent self-reflection via diary mining
         | 
| 64 | 
            +
            * [ ] Explainability chain trace visualizer
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            ### 🕸️ External Integrations
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            * [ ] WebAssembly interface (run agents in browser)
         | 
| 69 | 
            +
            * [ ] Ethereum / Polkadot adapters (smart contract gateways)
         | 
| 70 | 
            +
            * [ ] P2P synchronization modules (libp2p, dat, etc.)
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            ### 🔐 Formal Verification (Long-term)
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            * [ ] Mathematical proofs of correctness for EGP
         | 
| 75 | 
            +
            * [ ] Formal modeling of consensus mechanism
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            ---
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            ## 🧠 Source Acknowledgement
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            Feedback integrated from:
         | 
| 82 | 
            +
             | 
| 83 | 
            +
            * Copilot
         | 
| 84 | 
            +
            * Claude
         | 
| 85 | 
            +
            * Gemini
         | 
| 86 | 
            +
            * Qwen
         | 
| 87 | 
            +
            * DeepSeek
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            This roadmap is living — each new audit or issue may evolve the direction.
         | 
| 90 | 
            +
             | 
| 91 | 
            +
            > *"Build not only for intelligence, but for wisdom."*
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/LICENSE
    ADDED
    
    | @@ -0,0 +1,674 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
                                GNU GENERAL PUBLIC LICENSE
         | 
| 2 | 
            +
                                   Version 3, 29 June 2007
         | 
| 3 | 
            +
             | 
| 4 | 
            +
             Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
         | 
| 5 | 
            +
             Everyone is permitted to copy and distribute verbatim copies
         | 
| 6 | 
            +
             of this license document, but changing it is not allowed.
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                                        Preamble
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              The GNU General Public License is a free, copyleft license for
         | 
| 11 | 
            +
            software and other kinds of works.
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              The licenses for most software and other practical works are designed
         | 
| 14 | 
            +
            to take away your freedom to share and change the works.  By contrast,
         | 
| 15 | 
            +
            the GNU General Public License is intended to guarantee your freedom to
         | 
| 16 | 
            +
            share and change all versions of a program--to make sure it remains free
         | 
| 17 | 
            +
            software for all its users.  We, the Free Software Foundation, use the
         | 
| 18 | 
            +
            GNU General Public License for most of our software; it applies also to
         | 
| 19 | 
            +
            any other work released this way by its authors.  You can apply it to
         | 
| 20 | 
            +
            your programs, too.
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              When we speak of free software, we are referring to freedom, not
         | 
| 23 | 
            +
            price.  Our General Public Licenses are designed to make sure that you
         | 
| 24 | 
            +
            have the freedom to distribute copies of free software (and charge for
         | 
| 25 | 
            +
            them if you wish), that you receive source code or can get it if you
         | 
| 26 | 
            +
            want it, that you can change the software or use pieces of it in new
         | 
| 27 | 
            +
            free programs, and that you know you can do these things.
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              To protect your rights, we need to prevent others from denying you
         | 
| 30 | 
            +
            these rights or asking you to surrender the rights.  Therefore, you have
         | 
| 31 | 
            +
            certain responsibilities if you distribute copies of the software, or if
         | 
| 32 | 
            +
            you modify it: responsibilities to respect the freedom of others.
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              For example, if you distribute copies of such a program, whether
         | 
| 35 | 
            +
            gratis or for a fee, you must pass on to the recipients the same
         | 
| 36 | 
            +
            freedoms that you received.  You must make sure that they, too, receive
         | 
| 37 | 
            +
            or can get the source code.  And you must show them these terms so they
         | 
| 38 | 
            +
            know their rights.
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              Developers that use the GNU GPL protect your rights with two steps:
         | 
| 41 | 
            +
            (1) assert copyright on the software, and (2) offer you this License
         | 
| 42 | 
            +
            giving you legal permission to copy, distribute and/or modify it.
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              For the developers' and authors' protection, the GPL clearly explains
         | 
| 45 | 
            +
            that there is no warranty for this free software.  For both users' and
         | 
| 46 | 
            +
            authors' sake, the GPL requires that modified versions be marked as
         | 
| 47 | 
            +
            changed, so that their problems will not be attributed erroneously to
         | 
| 48 | 
            +
            authors of previous versions.
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              Some devices are designed to deny users access to install or run
         | 
| 51 | 
            +
            modified versions of the software inside them, although the manufacturer
         | 
| 52 | 
            +
            can do so.  This is fundamentally incompatible with the aim of
         | 
| 53 | 
            +
            protecting users' freedom to change the software.  The systematic
         | 
| 54 | 
            +
            pattern of such abuse occurs in the area of products for individuals to
         | 
| 55 | 
            +
            use, which is precisely where it is most unacceptable.  Therefore, we
         | 
| 56 | 
            +
            have designed this version of the GPL to prohibit the practice for those
         | 
| 57 | 
            +
            products.  If such problems arise substantially in other domains, we
         | 
| 58 | 
            +
            stand ready to extend this provision to those domains in future versions
         | 
| 59 | 
            +
            of the GPL, as needed to protect the freedom of users.
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              Finally, every program is threatened constantly by software patents.
         | 
| 62 | 
            +
            States should not allow patents to restrict development and use of
         | 
| 63 | 
            +
            software on general-purpose computers, but in those that do, we wish to
         | 
| 64 | 
            +
            avoid the special danger that patents applied to a free program could
         | 
| 65 | 
            +
            make it effectively proprietary.  To prevent this, the GPL assures that
         | 
| 66 | 
            +
            patents cannot be used to render the program non-free.
         | 
| 67 | 
            +
             | 
| 68 | 
            +
              The precise terms and conditions for copying, distribution and
         | 
| 69 | 
            +
            modification follow.
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                                   TERMS AND CONDITIONS
         | 
| 72 | 
            +
             | 
| 73 | 
            +
              0. Definitions.
         | 
| 74 | 
            +
             | 
| 75 | 
            +
              "This License" refers to version 3 of the GNU General Public License.
         | 
| 76 | 
            +
             | 
| 77 | 
            +
              "Copyright" also means copyright-like laws that apply to other kinds of
         | 
| 78 | 
            +
            works, such as semiconductor masks.
         | 
| 79 | 
            +
             | 
| 80 | 
            +
              "The Program" refers to any copyrightable work licensed under this
         | 
| 81 | 
            +
            License.  Each licensee is addressed as "you".  "Licensees" and
         | 
| 82 | 
            +
            "recipients" may be individuals or organizations.
         | 
| 83 | 
            +
             | 
| 84 | 
            +
              To "modify" a work means to copy from or adapt all or part of the work
         | 
| 85 | 
            +
            in a fashion requiring copyright permission, other than the making of an
         | 
| 86 | 
            +
            exact copy.  The resulting work is called a "modified version" of the
         | 
| 87 | 
            +
            earlier work or a work "based on" the earlier work.
         | 
| 88 | 
            +
             | 
| 89 | 
            +
              A "covered work" means either the unmodified Program or a work based
         | 
| 90 | 
            +
            on the Program.
         | 
| 91 | 
            +
             | 
| 92 | 
            +
              To "propagate" a work means to do anything with it that, without
         | 
| 93 | 
            +
            permission, would make you directly or secondarily liable for
         | 
| 94 | 
            +
            infringement under applicable copyright law, except executing it on a
         | 
| 95 | 
            +
            computer or modifying a private copy.  Propagation includes copying,
         | 
| 96 | 
            +
            distribution (with or without modification), making available to the
         | 
| 97 | 
            +
            public, and in some countries other activities as well.
         | 
| 98 | 
            +
             | 
| 99 | 
            +
              To "convey" a work means any kind of propagation that enables other
         | 
| 100 | 
            +
            parties to make or receive copies.  Mere interaction with a user through
         | 
| 101 | 
            +
            a computer network, with no transfer of a copy, is not conveying.
         | 
| 102 | 
            +
             | 
| 103 | 
            +
              An interactive user interface displays "Appropriate Legal Notices"
         | 
| 104 | 
            +
            to the extent that it includes a convenient and prominently visible
         | 
| 105 | 
            +
            feature that (1) displays an appropriate copyright notice, and (2)
         | 
| 106 | 
            +
            tells the user that there is no warranty for the work (except to the
         | 
| 107 | 
            +
            extent that warranties are provided), that licensees may convey the
         | 
| 108 | 
            +
            work under this License, and how to view a copy of this License.  If
         | 
| 109 | 
            +
            the interface presents a list of user commands or options, such as a
         | 
| 110 | 
            +
            menu, a prominent item in the list meets this criterion.
         | 
| 111 | 
            +
             | 
| 112 | 
            +
              1. Source Code.
         | 
| 113 | 
            +
             | 
| 114 | 
            +
              The "source code" for a work means the preferred form of the work
         | 
| 115 | 
            +
            for making modifications to it.  "Object code" means any non-source
         | 
| 116 | 
            +
            form of a work.
         | 
| 117 | 
            +
             | 
| 118 | 
            +
              A "Standard Interface" means an interface that either is an official
         | 
| 119 | 
            +
            standard defined by a recognized standards body, or, in the case of
         | 
| 120 | 
            +
            interfaces specified for a particular programming language, one that
         | 
| 121 | 
            +
            is widely used among developers working in that language.
         | 
| 122 | 
            +
             | 
| 123 | 
            +
              The "System Libraries" of an executable work include anything, other
         | 
| 124 | 
            +
            than the work as a whole, that (a) is included in the normal form of
         | 
| 125 | 
            +
            packaging a Major Component, but which is not part of that Major
         | 
| 126 | 
            +
            Component, and (b) serves only to enable use of the work with that
         | 
| 127 | 
            +
            Major Component, or to implement a Standard Interface for which an
         | 
| 128 | 
            +
            implementation is available to the public in source code form.  A
         | 
| 129 | 
            +
            "Major Component", in this context, means a major essential component
         | 
| 130 | 
            +
            (kernel, window system, and so on) of the specific operating system
         | 
| 131 | 
            +
            (if any) on which the executable work runs, or a compiler used to
         | 
| 132 | 
            +
            produce the work, or an object code interpreter used to run it.
         | 
| 133 | 
            +
             | 
| 134 | 
            +
              The "Corresponding Source" for a work in object code form means all
         | 
| 135 | 
            +
            the source code needed to generate, install, and (for an executable
         | 
| 136 | 
            +
            work) run the object code and to modify the work, including scripts to
         | 
| 137 | 
            +
            control those activities.  However, it does not include the work's
         | 
| 138 | 
            +
            System Libraries, or general-purpose tools or generally available free
         | 
| 139 | 
            +
            programs which are used unmodified in performing those activities but
         | 
| 140 | 
            +
            which are not part of the work.  For example, Corresponding Source
         | 
| 141 | 
            +
            includes interface definition files associated with source files for
         | 
| 142 | 
            +
            the work, and the source code for shared libraries and dynamically
         | 
| 143 | 
            +
            linked subprograms that the work is specifically designed to require,
         | 
| 144 | 
            +
            such as by intimate data communication or control flow between those
         | 
| 145 | 
            +
            subprograms and other parts of the work.
         | 
| 146 | 
            +
             | 
| 147 | 
            +
              The Corresponding Source need not include anything that users
         | 
| 148 | 
            +
            can regenerate automatically from other parts of the Corresponding
         | 
| 149 | 
            +
            Source.
         | 
| 150 | 
            +
             | 
| 151 | 
            +
              The Corresponding Source for a work in source code form is that
         | 
| 152 | 
            +
            same work.
         | 
| 153 | 
            +
             | 
| 154 | 
            +
              2. Basic Permissions.
         | 
| 155 | 
            +
             | 
| 156 | 
            +
              All rights granted under this License are granted for the term of
         | 
| 157 | 
            +
            copyright on the Program, and are irrevocable provided the stated
         | 
| 158 | 
            +
            conditions are met.  This License explicitly affirms your unlimited
         | 
| 159 | 
            +
            permission to run the unmodified Program.  The output from running a
         | 
| 160 | 
            +
            covered work is covered by this License only if the output, given its
         | 
| 161 | 
            +
            content, constitutes a covered work.  This License acknowledges your
         | 
| 162 | 
            +
            rights of fair use or other equivalent, as provided by copyright law.
         | 
| 163 | 
            +
             | 
| 164 | 
            +
              You may make, run and propagate covered works that you do not
         | 
| 165 | 
            +
            convey, without conditions so long as your license otherwise remains
         | 
| 166 | 
            +
            in force.  You may convey covered works to others for the sole purpose
         | 
| 167 | 
            +
            of having them make modifications exclusively for you, or provide you
         | 
| 168 | 
            +
            with facilities for running those works, provided that you comply with
         | 
| 169 | 
            +
            the terms of this License in conveying all material for which you do
         | 
| 170 | 
            +
            not control copyright.  Those thus making or running the covered works
         | 
| 171 | 
            +
            for you must do so exclusively on your behalf, under your direction
         | 
| 172 | 
            +
            and control, on terms that prohibit them from making any copies of
         | 
| 173 | 
            +
            your copyrighted material outside their relationship with you.
         | 
| 174 | 
            +
             | 
| 175 | 
            +
              Conveying under any other circumstances is permitted solely under
         | 
| 176 | 
            +
            the conditions stated below.  Sublicensing is not allowed; section 10
         | 
| 177 | 
            +
            makes it unnecessary.
         | 
| 178 | 
            +
             | 
| 179 | 
            +
              3. Protecting Users' Legal Rights From Anti-Circumvention Law.
         | 
| 180 | 
            +
             | 
| 181 | 
            +
              No covered work shall be deemed part of an effective technological
         | 
| 182 | 
            +
            measure under any applicable law fulfilling obligations under article
         | 
| 183 | 
            +
            11 of the WIPO copyright treaty adopted on 20 December 1996, or
         | 
| 184 | 
            +
            similar laws prohibiting or restricting circumvention of such
         | 
| 185 | 
            +
            measures.
         | 
| 186 | 
            +
             | 
| 187 | 
            +
              When you convey a covered work, you waive any legal power to forbid
         | 
| 188 | 
            +
            circumvention of technological measures to the extent such circumvention
         | 
| 189 | 
            +
            is effected by exercising rights under this License with respect to
         | 
| 190 | 
            +
            the covered work, and you disclaim any intention to limit operation or
         | 
| 191 | 
            +
            modification of the work as a means of enforcing, against the work's
         | 
| 192 | 
            +
            users, your or third parties' legal rights to forbid circumvention of
         | 
| 193 | 
            +
            technological measures.
         | 
| 194 | 
            +
             | 
| 195 | 
            +
              4. Conveying Verbatim Copies.
         | 
| 196 | 
            +
             | 
| 197 | 
            +
              You may convey verbatim copies of the Program's source code as you
         | 
| 198 | 
            +
            receive it, in any medium, provided that you conspicuously and
         | 
| 199 | 
            +
            appropriately publish on each copy an appropriate copyright notice;
         | 
| 200 | 
            +
            keep intact all notices stating that this License and any
         | 
| 201 | 
            +
            non-permissive terms added in accord with section 7 apply to the code;
         | 
| 202 | 
            +
            keep intact all notices of the absence of any warranty; and give all
         | 
| 203 | 
            +
            recipients a copy of this License along with the Program.
         | 
| 204 | 
            +
             | 
| 205 | 
            +
              You may charge any price or no price for each copy that you convey,
         | 
| 206 | 
            +
            and you may offer support or warranty protection for a fee.
         | 
| 207 | 
            +
             | 
| 208 | 
            +
              5. Conveying Modified Source Versions.
         | 
| 209 | 
            +
             | 
| 210 | 
            +
              You may convey a work based on the Program, or the modifications to
         | 
| 211 | 
            +
            produce it from the Program, in the form of source code under the
         | 
| 212 | 
            +
            terms of section 4, provided that you also meet all of these conditions:
         | 
| 213 | 
            +
             | 
| 214 | 
            +
                a) The work must carry prominent notices stating that you modified
         | 
| 215 | 
            +
                it, and giving a relevant date.
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                b) The work must carry prominent notices stating that it is
         | 
| 218 | 
            +
                released under this License and any conditions added under section
         | 
| 219 | 
            +
                7.  This requirement modifies the requirement in section 4 to
         | 
| 220 | 
            +
                "keep intact all notices".
         | 
| 221 | 
            +
             | 
| 222 | 
            +
                c) You must license the entire work, as a whole, under this
         | 
| 223 | 
            +
                License to anyone who comes into possession of a copy.  This
         | 
| 224 | 
            +
                License will therefore apply, along with any applicable section 7
         | 
| 225 | 
            +
                additional terms, to the whole of the work, and all its parts,
         | 
| 226 | 
            +
                regardless of how they are packaged.  This License gives no
         | 
| 227 | 
            +
                permission to license the work in any other way, but it does not
         | 
| 228 | 
            +
                invalidate such permission if you have separately received it.
         | 
| 229 | 
            +
             | 
| 230 | 
            +
                d) If the work has interactive user interfaces, each must display
         | 
| 231 | 
            +
                Appropriate Legal Notices; however, if the Program has interactive
         | 
| 232 | 
            +
                interfaces that do not display Appropriate Legal Notices, your
         | 
| 233 | 
            +
                work need not make them do so.
         | 
| 234 | 
            +
             | 
| 235 | 
            +
              A compilation of a covered work with other separate and independent
         | 
| 236 | 
            +
            works, which are not by their nature extensions of the covered work,
         | 
| 237 | 
            +
            and which are not combined with it such as to form a larger program,
         | 
| 238 | 
            +
            in or on a volume of a storage or distribution medium, is called an
         | 
| 239 | 
            +
            "aggregate" if the compilation and its resulting copyright are not
         | 
| 240 | 
            +
            used to limit the access or legal rights of the compilation's users
         | 
| 241 | 
            +
            beyond what the individual works permit.  Inclusion of a covered work
         | 
| 242 | 
            +
            in an aggregate does not cause this License to apply to the other
         | 
| 243 | 
            +
            parts of the aggregate.
         | 
| 244 | 
            +
             | 
| 245 | 
            +
              6. Conveying Non-Source Forms.
         | 
| 246 | 
            +
             | 
| 247 | 
            +
              You may convey a covered work in object code form under the terms
         | 
| 248 | 
            +
            of sections 4 and 5, provided that you also convey the
         | 
| 249 | 
            +
            machine-readable Corresponding Source under the terms of this License,
         | 
| 250 | 
            +
            in one of these ways:
         | 
| 251 | 
            +
             | 
| 252 | 
            +
                a) Convey the object code in, or embodied in, a physical product
         | 
| 253 | 
            +
                (including a physical distribution medium), accompanied by the
         | 
| 254 | 
            +
                Corresponding Source fixed on a durable physical medium
         | 
| 255 | 
            +
                customarily used for software interchange.
         | 
| 256 | 
            +
             | 
| 257 | 
            +
                b) Convey the object code in, or embodied in, a physical product
         | 
| 258 | 
            +
                (including a physical distribution medium), accompanied by a
         | 
| 259 | 
            +
                written offer, valid for at least three years and valid for as
         | 
| 260 | 
            +
                long as you offer spare parts or customer support for that product
         | 
| 261 | 
            +
                model, to give anyone who possesses the object code either (1) a
         | 
| 262 | 
            +
                copy of the Corresponding Source for all the software in the
         | 
| 263 | 
            +
                product that is covered by this License, on a durable physical
         | 
| 264 | 
            +
                medium customarily used for software interchange, for a price no
         | 
| 265 | 
            +
                more than your reasonable cost of physically performing this
         | 
| 266 | 
            +
                conveying of source, or (2) access to copy the
         | 
| 267 | 
            +
                Corresponding Source from a network server at no charge.
         | 
| 268 | 
            +
             | 
| 269 | 
            +
                c) Convey individual copies of the object code with a copy of the
         | 
| 270 | 
            +
                written offer to provide the Corresponding Source.  This
         | 
| 271 | 
            +
                alternative is allowed only occasionally and noncommercially, and
         | 
| 272 | 
            +
                only if you received the object code with such an offer, in accord
         | 
| 273 | 
            +
                with subsection 6b.
         | 
| 274 | 
            +
             | 
| 275 | 
            +
                d) Convey the object code by offering access from a designated
         | 
| 276 | 
            +
                place (gratis or for a charge), and offer equivalent access to the
         | 
| 277 | 
            +
                Corresponding Source in the same way through the same place at no
         | 
| 278 | 
            +
                further charge.  You need not require recipients to copy the
         | 
| 279 | 
            +
                Corresponding Source along with the object code.  If the place to
         | 
| 280 | 
            +
                copy the object code is a network server, the Corresponding Source
         | 
| 281 | 
            +
                may be on a different server (operated by you or a third party)
         | 
| 282 | 
            +
                that supports equivalent copying facilities, provided you maintain
         | 
| 283 | 
            +
                clear directions next to the object code saying where to find the
         | 
| 284 | 
            +
                Corresponding Source.  Regardless of what server hosts the
         | 
| 285 | 
            +
                Corresponding Source, you remain obligated to ensure that it is
         | 
| 286 | 
            +
                available for as long as needed to satisfy these requirements.
         | 
| 287 | 
            +
             | 
| 288 | 
            +
                e) Convey the object code using peer-to-peer transmission, provided
         | 
| 289 | 
            +
                you inform other peers where the object code and Corresponding
         | 
| 290 | 
            +
                Source of the work are being offered to the general public at no
         | 
| 291 | 
            +
                charge under subsection 6d.
         | 
| 292 | 
            +
             | 
| 293 | 
            +
              A separable portion of the object code, whose source code is excluded
         | 
| 294 | 
            +
            from the Corresponding Source as a System Library, need not be
         | 
| 295 | 
            +
            included in conveying the object code work.
         | 
| 296 | 
            +
             | 
| 297 | 
            +
              A "User Product" is either (1) a "consumer product", which means any
         | 
| 298 | 
            +
            tangible personal property which is normally used for personal, family,
         | 
| 299 | 
            +
            or household purposes, or (2) anything designed or sold for incorporation
         | 
| 300 | 
            +
            into a dwelling.  In determining whether a product is a consumer product,
         | 
| 301 | 
            +
            doubtful cases shall be resolved in favor of coverage.  For a particular
         | 
| 302 | 
            +
            product received by a particular user, "normally used" refers to a
         | 
| 303 | 
            +
            typical or common use of that class of product, regardless of the status
         | 
| 304 | 
            +
            of the particular user or of the way in which the particular user
         | 
| 305 | 
            +
            actually uses, or expects or is expected to use, the product.  A product
         | 
| 306 | 
            +
            is a consumer product regardless of whether the product has substantial
         | 
| 307 | 
            +
            commercial, industrial or non-consumer uses, unless such uses represent
         | 
| 308 | 
            +
            the only significant mode of use of the product.
         | 
| 309 | 
            +
             | 
| 310 | 
            +
              "Installation Information" for a User Product means any methods,
         | 
| 311 | 
            +
            procedures, authorization keys, or other information required to install
         | 
| 312 | 
            +
            and execute modified versions of a covered work in that User Product from
         | 
| 313 | 
            +
            a modified version of its Corresponding Source.  The information must
         | 
| 314 | 
            +
            suffice to ensure that the continued functioning of the modified object
         | 
| 315 | 
            +
            code is in no case prevented or interfered with solely because
         | 
| 316 | 
            +
            modification has been made.
         | 
| 317 | 
            +
             | 
| 318 | 
            +
              If you convey an object code work under this section in, or with, or
         | 
| 319 | 
            +
            specifically for use in, a User Product, and the conveying occurs as
         | 
| 320 | 
            +
            part of a transaction in which the right of possession and use of the
         | 
| 321 | 
            +
            User Product is transferred to the recipient in perpetuity or for a
         | 
| 322 | 
            +
            fixed term (regardless of how the transaction is characterized), the
         | 
| 323 | 
            +
            Corresponding Source conveyed under this section must be accompanied
         | 
| 324 | 
            +
            by the Installation Information.  But this requirement does not apply
         | 
| 325 | 
            +
            if neither you nor any third party retains the ability to install
         | 
| 326 | 
            +
            modified object code on the User Product (for example, the work has
         | 
| 327 | 
            +
            been installed in ROM).
         | 
| 328 | 
            +
             | 
| 329 | 
            +
              The requirement to provide Installation Information does not include a
         | 
| 330 | 
            +
            requirement to continue to provide support service, warranty, or updates
         | 
| 331 | 
            +
            for a work that has been modified or installed by the recipient, or for
         | 
| 332 | 
            +
            the User Product in which it has been modified or installed.  Access to a
         | 
| 333 | 
            +
            network may be denied when the modification itself materially and
         | 
| 334 | 
            +
            adversely affects the operation of the network or violates the rules and
         | 
| 335 | 
            +
            protocols for communication across the network.
         | 
| 336 | 
            +
             | 
| 337 | 
            +
              Corresponding Source conveyed, and Installation Information provided,
         | 
| 338 | 
            +
            in accord with this section must be in a format that is publicly
         | 
| 339 | 
            +
            documented (and with an implementation available to the public in
         | 
| 340 | 
            +
            source code form), and must require no special password or key for
         | 
| 341 | 
            +
            unpacking, reading or copying.
         | 
| 342 | 
            +
             | 
| 343 | 
            +
              7. Additional Terms.
         | 
| 344 | 
            +
             | 
| 345 | 
            +
              "Additional permissions" are terms that supplement the terms of this
         | 
| 346 | 
            +
            License by making exceptions from one or more of its conditions.
         | 
| 347 | 
            +
            Additional permissions that are applicable to the entire Program shall
         | 
| 348 | 
            +
            be treated as though they were included in this License, to the extent
         | 
| 349 | 
            +
            that they are valid under applicable law.  If additional permissions
         | 
| 350 | 
            +
            apply only to part of the Program, that part may be used separately
         | 
| 351 | 
            +
            under those permissions, but the entire Program remains governed by
         | 
| 352 | 
            +
            this License without regard to the additional permissions.
         | 
| 353 | 
            +
             | 
| 354 | 
            +
              When you convey a copy of a covered work, you may at your option
         | 
| 355 | 
            +
            remove any additional permissions from that copy, or from any part of
         | 
| 356 | 
            +
            it.  (Additional permissions may be written to require their own
         | 
| 357 | 
            +
            removal in certain cases when you modify the work.)  You may place
         | 
| 358 | 
            +
            additional permissions on material, added by you to a covered work,
         | 
| 359 | 
            +
            for which you have or can give appropriate copyright permission.
         | 
| 360 | 
            +
             | 
| 361 | 
            +
              Notwithstanding any other provision of this License, for material you
         | 
| 362 | 
            +
            add to a covered work, you may (if authorized by the copyright holders of
         | 
| 363 | 
            +
            that material) supplement the terms of this License with terms:
         | 
| 364 | 
            +
             | 
| 365 | 
            +
                a) Disclaiming warranty or limiting liability differently from the
         | 
| 366 | 
            +
                terms of sections 15 and 16 of this License; or
         | 
| 367 | 
            +
             | 
| 368 | 
            +
                b) Requiring preservation of specified reasonable legal notices or
         | 
| 369 | 
            +
                author attributions in that material or in the Appropriate Legal
         | 
| 370 | 
            +
                Notices displayed by works containing it; or
         | 
| 371 | 
            +
             | 
| 372 | 
            +
                c) Prohibiting misrepresentation of the origin of that material, or
         | 
| 373 | 
            +
                requiring that modified versions of such material be marked in
         | 
| 374 | 
            +
                reasonable ways as different from the original version; or
         | 
| 375 | 
            +
             | 
| 376 | 
            +
                d) Limiting the use for publicity purposes of names of licensors or
         | 
| 377 | 
            +
                authors of the material; or
         | 
| 378 | 
            +
             | 
| 379 | 
            +
                e) Declining to grant rights under trademark law for use of some
         | 
| 380 | 
            +
                trade names, trademarks, or service marks; or
         | 
| 381 | 
            +
             | 
| 382 | 
            +
                f) Requiring indemnification of licensors and authors of that
         | 
| 383 | 
            +
                material by anyone who conveys the material (or modified versions of
         | 
| 384 | 
            +
                it) with contractual assumptions of liability to the recipient, for
         | 
| 385 | 
            +
                any liability that these contractual assumptions directly impose on
         | 
| 386 | 
            +
                those licensors and authors.
         | 
| 387 | 
            +
             | 
| 388 | 
            +
              All other non-permissive additional terms are considered "further
         | 
| 389 | 
            +
            restrictions" within the meaning of section 10.  If the Program as you
         | 
| 390 | 
            +
            received it, or any part of it, contains a notice stating that it is
         | 
| 391 | 
            +
            governed by this License along with a term that is a further
         | 
| 392 | 
            +
            restriction, you may remove that term.  If a license document contains
         | 
| 393 | 
            +
            a further restriction but permits relicensing or conveying under this
         | 
| 394 | 
            +
            License, you may add to a covered work material governed by the terms
         | 
| 395 | 
            +
            of that license document, provided that the further restriction does
         | 
| 396 | 
            +
            not survive such relicensing or conveying.
         | 
| 397 | 
            +
             | 
| 398 | 
            +
              If you add terms to a covered work in accord with this section, you
         | 
| 399 | 
            +
            must place, in the relevant source files, a statement of the
         | 
| 400 | 
            +
            additional terms that apply to those files, or a notice indicating
         | 
| 401 | 
            +
            where to find the applicable terms.
         | 
| 402 | 
            +
             | 
| 403 | 
            +
              Additional terms, permissive or non-permissive, may be stated in the
         | 
| 404 | 
            +
            form of a separately written license, or stated as exceptions;
         | 
| 405 | 
            +
            the above requirements apply either way.
         | 
| 406 | 
            +
             | 
| 407 | 
            +
              8. Termination.
         | 
| 408 | 
            +
             | 
| 409 | 
            +
              You may not propagate or modify a covered work except as expressly
         | 
| 410 | 
            +
            provided under this License.  Any attempt otherwise to propagate or
         | 
| 411 | 
            +
            modify it is void, and will automatically terminate your rights under
         | 
| 412 | 
            +
            this License (including any patent licenses granted under the third
         | 
| 413 | 
            +
            paragraph of section 11).
         | 
| 414 | 
            +
             | 
| 415 | 
            +
              However, if you cease all violation of this License, then your
         | 
| 416 | 
            +
            license from a particular copyright holder is reinstated (a)
         | 
| 417 | 
            +
            provisionally, unless and until the copyright holder explicitly and
         | 
| 418 | 
            +
            finally terminates your license, and (b) permanently, if the copyright
         | 
| 419 | 
            +
            holder fails to notify you of the violation by some reasonable means
         | 
| 420 | 
            +
            prior to 60 days after the cessation.
         | 
| 421 | 
            +
             | 
| 422 | 
            +
              Moreover, your license from a particular copyright holder is
         | 
| 423 | 
            +
            reinstated permanently if the copyright holder notifies you of the
         | 
| 424 | 
            +
            violation by some reasonable means, this is the first time you have
         | 
| 425 | 
            +
            received notice of violation of this License (for any work) from that
         | 
| 426 | 
            +
            copyright holder, and you cure the violation prior to 30 days after
         | 
| 427 | 
            +
            your receipt of the notice.
         | 
| 428 | 
            +
             | 
| 429 | 
            +
              Termination of your rights under this section does not terminate the
         | 
| 430 | 
            +
            licenses of parties who have received copies or rights from you under
         | 
| 431 | 
            +
            this License.  If your rights have been terminated and not permanently
         | 
| 432 | 
            +
            reinstated, you do not qualify to receive new licenses for the same
         | 
| 433 | 
            +
            material under section 10.
         | 
| 434 | 
            +
             | 
| 435 | 
            +
              9. Acceptance Not Required for Having Copies.
         | 
| 436 | 
            +
             | 
| 437 | 
            +
              You are not required to accept this License in order to receive or
         | 
| 438 | 
            +
            run a copy of the Program.  Ancillary propagation of a covered work
         | 
| 439 | 
            +
            occurring solely as a consequence of using peer-to-peer transmission
         | 
| 440 | 
            +
            to receive a copy likewise does not require acceptance.  However,
         | 
| 441 | 
            +
            nothing other than this License grants you permission to propagate or
         | 
| 442 | 
            +
            modify any covered work.  These actions infringe copyright if you do
         | 
| 443 | 
            +
            not accept this License.  Therefore, by modifying or propagating a
         | 
| 444 | 
            +
            covered work, you indicate your acceptance of this License to do so.
         | 
| 445 | 
            +
             | 
| 446 | 
            +
              10. Automatic Licensing of Downstream Recipients.
         | 
| 447 | 
            +
             | 
| 448 | 
            +
              Each time you convey a covered work, the recipient automatically
         | 
| 449 | 
            +
            receives a license from the original licensors, to run, modify and
         | 
| 450 | 
            +
            propagate that work, subject to this License.  You are not responsible
         | 
| 451 | 
            +
            for enforcing compliance by third parties with this License.
         | 
| 452 | 
            +
             | 
| 453 | 
            +
              An "entity transaction" is a transaction transferring control of an
         | 
| 454 | 
            +
            organization, or substantially all assets of one, or subdividing an
         | 
| 455 | 
            +
            organization, or merging organizations.  If propagation of a covered
         | 
| 456 | 
            +
            work results from an entity transaction, each party to that
         | 
| 457 | 
            +
            transaction who receives a copy of the work also receives whatever
         | 
| 458 | 
            +
            licenses to the work the party's predecessor in interest had or could
         | 
| 459 | 
            +
            give under the previous paragraph, plus a right to possession of the
         | 
| 460 | 
            +
            Corresponding Source of the work from the predecessor in interest, if
         | 
| 461 | 
            +
            the predecessor has it or can get it with reasonable efforts.
         | 
| 462 | 
            +
             | 
| 463 | 
            +
              You may not impose any further restrictions on the exercise of the
         | 
| 464 | 
            +
            rights granted or affirmed under this License.  For example, you may
         | 
| 465 | 
            +
            not impose a license fee, royalty, or other charge for exercise of
         | 
| 466 | 
            +
            rights granted under this License, and you may not initiate litigation
         | 
| 467 | 
            +
            (including a cross-claim or counterclaim in a lawsuit) alleging that
         | 
| 468 | 
            +
            any patent claim is infringed by making, using, selling, offering for
         | 
| 469 | 
            +
            sale, or importing the Program or any portion of it.
         | 
| 470 | 
            +
             | 
| 471 | 
            +
              11. Patents.
         | 
| 472 | 
            +
             | 
| 473 | 
            +
              A "contributor" is a copyright holder who authorizes use under this
         | 
| 474 | 
            +
            License of the Program or a work on which the Program is based.  The
         | 
| 475 | 
            +
            work thus licensed is called the contributor's "contributor version".
         | 
| 476 | 
            +
             | 
| 477 | 
            +
              A contributor's "essential patent claims" are all patent claims
         | 
| 478 | 
            +
            owned or controlled by the contributor, whether already acquired or
         | 
| 479 | 
            +
            hereafter acquired, that would be infringed by some manner, permitted
         | 
| 480 | 
            +
            by this License, of making, using, or selling its contributor version,
         | 
| 481 | 
            +
            but do not include claims that would be infringed only as a
         | 
| 482 | 
            +
            consequence of further modification of the contributor version.  For
         | 
| 483 | 
            +
            purposes of this definition, "control" includes the right to grant
         | 
| 484 | 
            +
            patent sublicenses in a manner consistent with the requirements of
         | 
| 485 | 
            +
            this License.
         | 
| 486 | 
            +
             | 
| 487 | 
            +
              Each contributor grants you a non-exclusive, worldwide, royalty-free
         | 
| 488 | 
            +
            patent license under the contributor's essential patent claims, to
         | 
| 489 | 
            +
            make, use, sell, offer for sale, import and otherwise run, modify and
         | 
| 490 | 
            +
            propagate the contents of its contributor version.
         | 
| 491 | 
            +
             | 
| 492 | 
            +
              In the following three paragraphs, a "patent license" is any express
         | 
| 493 | 
            +
            agreement or commitment, however denominated, not to enforce a patent
         | 
| 494 | 
            +
            (such as an express permission to practice a patent or covenant not to
         | 
| 495 | 
            +
            sue for patent infringement).  To "grant" such a patent license to a
         | 
| 496 | 
            +
            party means to make such an agreement or commitment not to enforce a
         | 
| 497 | 
            +
            patent against the party.
         | 
| 498 | 
            +
             | 
| 499 | 
            +
              If you convey a covered work, knowingly relying on a patent license,
         | 
| 500 | 
            +
            and the Corresponding Source of the work is not available for anyone
         | 
| 501 | 
            +
            to copy, free of charge and under the terms of this License, through a
         | 
| 502 | 
            +
            publicly available network server or other readily accessible means,
         | 
| 503 | 
            +
            then you must either (1) cause the Corresponding Source to be so
         | 
| 504 | 
            +
            available, or (2) arrange to deprive yourself of the benefit of the
         | 
| 505 | 
            +
            patent license for this particular work, or (3) arrange, in a manner
         | 
| 506 | 
            +
            consistent with the requirements of this License, to extend the patent
         | 
| 507 | 
            +
            license to downstream recipients.  "Knowingly relying" means you have
         | 
| 508 | 
            +
            actual knowledge that, but for the patent license, your conveying the
         | 
| 509 | 
            +
            covered work in a country, or your recipient's use of the covered work
         | 
| 510 | 
            +
            in a country, would infringe one or more identifiable patents in that
         | 
| 511 | 
            +
            country that you have reason to believe are valid.
         | 
| 512 | 
            +
             | 
| 513 | 
            +
              If, pursuant to or in connection with a single transaction or
         | 
| 514 | 
            +
            arrangement, you convey, or propagate by procuring conveyance of, a
         | 
| 515 | 
            +
            covered work, and grant a patent license to some of the parties
         | 
| 516 | 
            +
            receiving the covered work authorizing them to use, propagate, modify
         | 
| 517 | 
            +
            or convey a specific copy of the covered work, then the patent license
         | 
| 518 | 
            +
            you grant is automatically extended to all recipients of the covered
         | 
| 519 | 
            +
            work and works based on it.
         | 
| 520 | 
            +
             | 
| 521 | 
            +
              A patent license is "discriminatory" if it does not include within
         | 
| 522 | 
            +
            the scope of its coverage, prohibits the exercise of, or is
         | 
| 523 | 
            +
            conditioned on the non-exercise of one or more of the rights that are
         | 
| 524 | 
            +
            specifically granted under this License.  You may not convey a covered
         | 
| 525 | 
            +
            work if you are a party to an arrangement with a third party that is
         | 
| 526 | 
            +
            in the business of distributing software, under which you make payment
         | 
| 527 | 
            +
            to the third party based on the extent of your activity of conveying
         | 
| 528 | 
            +
            the work, and under which the third party grants, to any of the
         | 
| 529 | 
            +
            parties who would receive the covered work from you, a discriminatory
         | 
| 530 | 
            +
            patent license (a) in connection with copies of the covered work
         | 
| 531 | 
            +
            conveyed by you (or copies made from those copies), or (b) primarily
         | 
| 532 | 
            +
            for and in connection with specific products or compilations that
         | 
| 533 | 
            +
            contain the covered work, unless you entered into that arrangement,
         | 
| 534 | 
            +
            or that patent license was granted, prior to 28 March 2007.
         | 
| 535 | 
            +
             | 
| 536 | 
            +
              Nothing in this License shall be construed as excluding or limiting
         | 
| 537 | 
            +
            any implied license or other defenses to infringement that may
         | 
| 538 | 
            +
            otherwise be available to you under applicable patent law.
         | 
| 539 | 
            +
             | 
| 540 | 
            +
              12. No Surrender of Others' Freedom.
         | 
| 541 | 
            +
             | 
| 542 | 
            +
              If conditions are imposed on you (whether by court order, agreement or
         | 
| 543 | 
            +
            otherwise) that contradict the conditions of this License, they do not
         | 
| 544 | 
            +
            excuse you from the conditions of this License.  If you cannot convey a
         | 
| 545 | 
            +
            covered work so as to satisfy simultaneously your obligations under this
         | 
| 546 | 
            +
            License and any other pertinent obligations, then as a consequence you may
         | 
| 547 | 
            +
            not convey it at all.  For example, if you agree to terms that obligate you
         | 
| 548 | 
            +
            to collect a royalty for further conveying from those to whom you convey
         | 
| 549 | 
            +
            the Program, the only way you could satisfy both those terms and this
         | 
| 550 | 
            +
            License would be to refrain entirely from conveying the Program.
         | 
| 551 | 
            +
             | 
| 552 | 
            +
              13. Use with the GNU Affero General Public License.
         | 
| 553 | 
            +
             | 
| 554 | 
            +
              Notwithstanding any other provision of this License, you have
         | 
| 555 | 
            +
            permission to link or combine any covered work with a work licensed
         | 
| 556 | 
            +
            under version 3 of the GNU Affero General Public License into a single
         | 
| 557 | 
            +
            combined work, and to convey the resulting work.  The terms of this
         | 
| 558 | 
            +
            License will continue to apply to the part which is the covered work,
         | 
| 559 | 
            +
            but the special requirements of the GNU Affero General Public License,
         | 
| 560 | 
            +
            section 13, concerning interaction through a network will apply to the
         | 
| 561 | 
            +
            combination as such.
         | 
| 562 | 
            +
             | 
| 563 | 
            +
              14. Revised Versions of this License.
         | 
| 564 | 
            +
             | 
| 565 | 
            +
              The Free Software Foundation may publish revised and/or new versions of
         | 
| 566 | 
            +
            the GNU General Public License from time to time.  Such new versions will
         | 
| 567 | 
            +
            be similar in spirit to the present version, but may differ in detail to
         | 
| 568 | 
            +
            address new problems or concerns.
         | 
| 569 | 
            +
             | 
| 570 | 
            +
              Each version is given a distinguishing version number.  If the
         | 
| 571 | 
            +
            Program specifies that a certain numbered version of the GNU General
         | 
| 572 | 
            +
            Public License "or any later version" applies to it, you have the
         | 
| 573 | 
            +
            option of following the terms and conditions either of that numbered
         | 
| 574 | 
            +
            version or of any later version published by the Free Software
         | 
| 575 | 
            +
            Foundation.  If the Program does not specify a version number of the
         | 
| 576 | 
            +
            GNU General Public License, you may choose any version ever published
         | 
| 577 | 
            +
            by the Free Software Foundation.
         | 
| 578 | 
            +
             | 
| 579 | 
            +
              If the Program specifies that a proxy can decide which future
         | 
| 580 | 
            +
            versions of the GNU General Public License can be used, that proxy's
         | 
| 581 | 
            +
            public statement of acceptance of a version permanently authorizes you
         | 
| 582 | 
            +
            to choose that version for the Program.
         | 
| 583 | 
            +
             | 
| 584 | 
            +
              Later license versions may give you additional or different
         | 
| 585 | 
            +
            permissions.  However, no additional obligations are imposed on any
         | 
| 586 | 
            +
            author or copyright holder as a result of your choosing to follow a
         | 
| 587 | 
            +
            later version.
         | 
| 588 | 
            +
             | 
| 589 | 
            +
              15. Disclaimer of Warranty.
         | 
| 590 | 
            +
             | 
| 591 | 
            +
              THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
         | 
| 592 | 
            +
            APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
         | 
| 593 | 
            +
            HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
         | 
| 594 | 
            +
            OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
         | 
| 595 | 
            +
            THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
         | 
| 596 | 
            +
            PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
         | 
| 597 | 
            +
            IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
         | 
| 598 | 
            +
            ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
         | 
| 599 | 
            +
             | 
| 600 | 
            +
              16. Limitation of Liability.
         | 
| 601 | 
            +
             | 
| 602 | 
            +
              IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
         | 
| 603 | 
            +
            WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
         | 
| 604 | 
            +
            THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
         | 
| 605 | 
            +
            GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
         | 
| 606 | 
            +
            USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
         | 
| 607 | 
            +
            DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
         | 
| 608 | 
            +
            PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
         | 
| 609 | 
            +
            EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
         | 
| 610 | 
            +
            SUCH DAMAGES.
         | 
| 611 | 
            +
             | 
| 612 | 
            +
              17. Interpretation of Sections 15 and 16.
         | 
| 613 | 
            +
             | 
| 614 | 
            +
              If the disclaimer of warranty and limitation of liability provided
         | 
| 615 | 
            +
            above cannot be given local legal effect according to their terms,
         | 
| 616 | 
            +
            reviewing courts shall apply local law that most closely approximates
         | 
| 617 | 
            +
            an absolute waiver of all civil liability in connection with the
         | 
| 618 | 
            +
            Program, unless a warranty or assumption of liability accompanies a
         | 
| 619 | 
            +
            copy of the Program in return for a fee.
         | 
| 620 | 
            +
             | 
| 621 | 
            +
                                 END OF TERMS AND CONDITIONS
         | 
| 622 | 
            +
             | 
| 623 | 
            +
                        How to Apply These Terms to Your New Programs
         | 
| 624 | 
            +
             | 
| 625 | 
            +
              If you develop a new program, and you want it to be of the greatest
         | 
| 626 | 
            +
            possible use to the public, the best way to achieve this is to make it
         | 
| 627 | 
            +
            free software which everyone can redistribute and change under these terms.
         | 
| 628 | 
            +
             | 
| 629 | 
            +
              To do so, attach the following notices to the program.  It is safest
         | 
| 630 | 
            +
            to attach them to the start of each source file to most effectively
         | 
| 631 | 
            +
            state the exclusion of warranty; and each file should have at least
         | 
| 632 | 
            +
            the "copyright" line and a pointer to where the full notice is found.
         | 
| 633 | 
            +
             | 
| 634 | 
            +
                <one line to give the program's name and a brief idea of what it does.>
         | 
| 635 | 
            +
                Copyright (C) <year>  <name of author>
         | 
| 636 | 
            +
             | 
| 637 | 
            +
                This program is free software: you can redistribute it and/or modify
         | 
| 638 | 
            +
                it under the terms of the GNU General Public License as published by
         | 
| 639 | 
            +
                the Free Software Foundation, either version 3 of the License, or
         | 
| 640 | 
            +
                (at your option) any later version.
         | 
| 641 | 
            +
             | 
| 642 | 
            +
                This program is distributed in the hope that it will be useful,
         | 
| 643 | 
            +
                but WITHOUT ANY WARRANTY; without even the implied warranty of
         | 
| 644 | 
            +
                MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
         | 
| 645 | 
            +
                GNU General Public License for more details.
         | 
| 646 | 
            +
             | 
| 647 | 
            +
                You should have received a copy of the GNU General Public License
         | 
| 648 | 
            +
                along with this program.  If not, see <https://www.gnu.org/licenses/>.
         | 
| 649 | 
            +
             | 
| 650 | 
            +
            Also add information on how to contact you by electronic and paper mail.
         | 
| 651 | 
            +
             | 
| 652 | 
            +
              If the program does terminal interaction, make it output a short
         | 
| 653 | 
            +
            notice like this when it starts in an interactive mode:
         | 
| 654 | 
            +
             | 
| 655 | 
            +
                <program>  Copyright (C) <year>  <name of author>
         | 
| 656 | 
            +
                This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
         | 
| 657 | 
            +
                This is free software, and you are welcome to redistribute it
         | 
| 658 | 
            +
                under certain conditions; type `show c' for details.
         | 
| 659 | 
            +
             | 
| 660 | 
            +
            The hypothetical commands `show w' and `show c' should show the appropriate
         | 
| 661 | 
            +
            parts of the General Public License.  Of course, your program's commands
         | 
| 662 | 
            +
            might be different; for a GUI interface, you would use an "about box".
         | 
| 663 | 
            +
             | 
| 664 | 
            +
              You should also get your employer (if you work as a programmer) or school,
         | 
| 665 | 
            +
            if any, to sign a "copyright disclaimer" for the program, if necessary.
         | 
| 666 | 
            +
            For more information on this, and how to apply and follow the GNU GPL, see
         | 
| 667 | 
            +
            <https://www.gnu.org/licenses/>.
         | 
| 668 | 
            +
             | 
| 669 | 
            +
              The GNU General Public License does not permit incorporating your program
         | 
| 670 | 
            +
            into proprietary programs.  If your program is a subroutine library, you
         | 
| 671 | 
            +
            may consider it more useful to permit linking proprietary applications with
         | 
| 672 | 
            +
            the library.  If this is what you want to do, use the GNU Lesser General
         | 
| 673 | 
            +
            Public License instead of this License.  But first, please read
         | 
| 674 | 
            +
            <https://www.gnu.org/licenses/why-not-lgpl.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/agents/_old/concept_store.py
    ADDED
    
    | @@ -0,0 +1,147 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # tools/concept_store.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import uuid
         | 
| 4 | 
            +
            from typing import Dict, List, Optional
         | 
| 5 | 
            +
            from models import GraphExport
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            class Concept:
         | 
| 8 | 
            +
                def __init__(
         | 
| 9 | 
            +
                    self,
         | 
| 10 | 
            +
                    id: Optional[str] = None,
         | 
| 11 | 
            +
                    label: str = "",
         | 
| 12 | 
            +
                    description: str = "",
         | 
| 13 | 
            +
                    tags: Optional[List[str]] = None
         | 
| 14 | 
            +
                ):
         | 
| 15 | 
            +
                    self.id = id or str(uuid.uuid4())
         | 
| 16 | 
            +
                    self.label = label
         | 
| 17 | 
            +
                    self.description = description
         | 
| 18 | 
            +
                    self.tags = tags or []
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def to_dict(self):
         | 
| 21 | 
            +
                    return {
         | 
| 22 | 
            +
                        "id": self.id,
         | 
| 23 | 
            +
                        "label": self.label,
         | 
| 24 | 
            +
                        "description": self.description,
         | 
| 25 | 
            +
                        "tags": self.tags
         | 
| 26 | 
            +
                    }
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                @staticmethod
         | 
| 29 | 
            +
                def from_dict(data):
         | 
| 30 | 
            +
                    return Concept(
         | 
| 31 | 
            +
                        id=data.get("id"),
         | 
| 32 | 
            +
                        label=data.get("label", ""),
         | 
| 33 | 
            +
                        description=data.get("description", ""),
         | 
| 34 | 
            +
                        tags=data.get("tags", [])
         | 
| 35 | 
            +
                    )
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            class Edge:
         | 
| 38 | 
            +
                def __init__(self, source: str, target: str, relation: str = "related_to"):
         | 
| 39 | 
            +
                    self.source = source
         | 
| 40 | 
            +
                    self.target = target
         | 
| 41 | 
            +
                    self.relation = relation
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def to_dict(self):
         | 
| 44 | 
            +
                    return {
         | 
| 45 | 
            +
                        "source": self.source,
         | 
| 46 | 
            +
                        "target": self.target,
         | 
| 47 | 
            +
                        "relation": self.relation
         | 
| 48 | 
            +
                    }
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                @staticmethod
         | 
| 51 | 
            +
                def from_dict(data):
         | 
| 52 | 
            +
                    return Edge(
         | 
| 53 | 
            +
                        source=data["source"],
         | 
| 54 | 
            +
                        target=data["target"],
         | 
| 55 | 
            +
                        relation=data.get("relation", "related_to")
         | 
| 56 | 
            +
                    )
         | 
| 57 | 
            +
             | 
| 58 | 
            +
             | 
| 59 | 
            +
            class ConceptStore:
         | 
| 60 | 
            +
                def __init__(self):
         | 
| 61 | 
            +
                    self.concepts: Dict[str, Concept] = {}
         | 
| 62 | 
            +
                    self.edges: List[Edge] = []
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                def add(self, concept: Concept):
         | 
| 65 | 
            +
                    self.concepts[concept.id] = concept
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                def get(self, concept_id: str) -> Optional[dict]:
         | 
| 68 | 
            +
                    concept = self.concepts.get(concept_id)
         | 
| 69 | 
            +
                    return concept.to_dict() if concept else None
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                def add_edge(self, edge: Edge):
         | 
| 72 | 
            +
                    if not any(
         | 
| 73 | 
            +
                        e.source == edge.source and
         | 
| 74 | 
            +
                        e.target == edge.target and
         | 
| 75 | 
            +
                        e.relation == edge.relation
         | 
| 76 | 
            +
                        for e in self.edges
         | 
| 77 | 
            +
                    ):
         | 
| 78 | 
            +
                        self.edges.append(edge)
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                def find_by_label(self, label: str) -> Optional[Concept]:
         | 
| 81 | 
            +
                    for c in self.concepts.values():
         | 
| 82 | 
            +
                        if c.label == label:
         | 
| 83 | 
            +
                            return c
         | 
| 84 | 
            +
                    return None
         | 
| 85 | 
            +
                
         | 
| 86 | 
            +
                def import_from_json(self, data: dict) -> dict:
         | 
| 87 | 
            +
                    nodes = data.get("nodes", [])
         | 
| 88 | 
            +
                    edges = data.get("edges", [])
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                    if not isinstance(nodes, list) or not isinstance(edges, list):
         | 
| 91 | 
            +
                        raise ValueError("Invalid format: 'nodes' and 'edges' must be lists")
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                    imported_nodes = 0
         | 
| 94 | 
            +
                    imported_edges = 0
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                    for c in nodes:
         | 
| 97 | 
            +
                        try:
         | 
| 98 | 
            +
                            concept = Concept.from_dict(c)
         | 
| 99 | 
            +
                            self.add(concept)
         | 
| 100 | 
            +
                            imported_nodes += 1
         | 
| 101 | 
            +
                        except Exception as e:
         | 
| 102 | 
            +
                            print(f"Failed to import concept: {e}")
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                    for e in edges:
         | 
| 105 | 
            +
                        try:
         | 
| 106 | 
            +
                            edge = Edge.from_dict(e)
         | 
| 107 | 
            +
                            self.add_edge(edge)
         | 
| 108 | 
            +
                            imported_edges += 1
         | 
| 109 | 
            +
                        except Exception as e:
         | 
| 110 | 
            +
                            print(f"Failed to import edge: {e}")
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                    return {
         | 
| 113 | 
            +
                        "status": "ok",
         | 
| 114 | 
            +
                        "imported_nodes": imported_nodes,
         | 
| 115 | 
            +
                        "imported_edges": imported_edges
         | 
| 116 | 
            +
                    }
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                def export_as_json(self) -> GraphExport:
         | 
| 119 | 
            +
                    return GraphExport(
         | 
| 120 | 
            +
                        nodes=[c.to_dict() for c in self.concepts.values()],
         | 
| 121 | 
            +
                        edges=[e.to_dict() for e in self.edges]
         | 
| 122 | 
            +
                    )
         | 
| 123 | 
            +
                
         | 
| 124 | 
            +
                def all_concepts(self):
         | 
| 125 | 
            +
                    return [c.to_dict() for c in self.concepts.values()]
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                def all_edges(self):
         | 
| 128 | 
            +
                    return [e.to_dict() for e in self.edges]
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                def remove_concept(self, concept_id: str):
         | 
| 131 | 
            +
                    if concept_id in self.concepts:
         | 
| 132 | 
            +
                        del self.concepts[concept_id]
         | 
| 133 | 
            +
                        self.edges = [e for e in self.edges if e.source != concept_id and e.target != concept_id]
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                def remove_edge(self, source_id: str, target_id: str, relation: str):
         | 
| 136 | 
            +
                    self.edges = [
         | 
| 137 | 
            +
                        e for e in self.edges
         | 
| 138 | 
            +
                        if not (e.source == source_id and e.target == target_id and e.relation == relation)
         | 
| 139 | 
            +
                    ]
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                def debug_print(self):
         | 
| 142 | 
            +
                    print("Concepts:")
         | 
| 143 | 
            +
                    for c in self.concepts.values():
         | 
| 144 | 
            +
                        print(c.to_dict())
         | 
| 145 | 
            +
                    print("\nEdges:")
         | 
| 146 | 
            +
                    for e in self.edges:
         | 
| 147 | 
            +
                        print(e.to_dict())
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/_old/db_structure.md
    ADDED
    
    | @@ -0,0 +1,223 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            ## 📦 HMP-Agent: Структура БД (v0.3, человекочитаемый формат)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ---
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ### 🧠 Когнитивная память (Concept Graph)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            #### 🧠 `memory_concepts`
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            **Назначение:**
         | 
| 10 | 
            +
            Хранение концептов (единиц когнитивной памяти): понятий, фактов, образов, внутренних конструкций и внешних знаний.
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            **Поля:**
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            * `id: INTEGER` — первичный ключ.
         | 
| 15 | 
            +
            * `label: TEXT` — человекочитаемое имя концепта.
         | 
| 16 | 
            +
            * `type: TEXT` — тип концепта (`idea`, `object`, `goal`, `fact`, `memory_snapshot`, `mesh_entity`, …).
         | 
| 17 | 
            +
            * `content: TEXT` — JSON-объект с содержанием концепта (например, описание, параметры, вложенные идеи).
         | 
| 18 | 
            +
            * `context: TEXT` — дополнительный контекст (например, источник, ссылка на событие).
         | 
| 19 | 
            +
            * `created_at: TIMESTAMP` — дата создания.
         | 
| 20 | 
            +
            * `updated_at: TIMESTAMP` — дата последнего обновления.
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            **Ключевые поля:** `id`, `label`
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            **Связи:**
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            * Ссылается из `memory_links.from_id` и `to_id`
         | 
| 27 | 
            +
            * Используется в `cognitive_cycles`, `hypotheses`, `reflections`, `reasoning_traces`
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            ---
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            #### 🔗 `memory_links`
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            **Назначение:**
         | 
| 34 | 
            +
            Определение связей между концептами — формирование когнитивного графа.
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            **Поля:**
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            * `id: INTEGER` — первичный ключ.
         | 
| 39 | 
            +
            * `from_id: INTEGER` — ID исходного концепта.
         | 
| 40 | 
            +
            * `to_id: INTEGER` — ID связанного концепта.
         | 
| 41 | 
            +
            * `relation: TEXT` — тип связи (`causes`, `associated_with`, `contradicts`, …).
         | 
| 42 | 
            +
            * `weight: REAL` — значимость или сила связи (по умолчанию 1.0).
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            **Ключевые поля:** `id`, `from_id`, `to_id`
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            **Связи:**
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            * `from_id`, `to_id → memory_concepts(id)`
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            ---
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            ## 📜 События, действия, сообщения
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            #### 🧩 `cognitive_events`
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            **Назначение:**
         | 
| 57 | 
            +
            Журнал восприятия, действий и входящих/исходящих сообщений.
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            **Поля:**
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            * `id: INTEGER` — первичный ключ.
         | 
| 62 | 
            +
            * `event_type: TEXT` — тип события (`input`, `output`, `message`, `action`, `mesh`, `internal`).
         | 
| 63 | 
            +
            * `payload: TEXT` — сериализованные данные (обычно JSON).
         | 
| 64 | 
            +
            * `source: TEXT` — источник события (например, ID mesh-пира).
         | 
| 65 | 
            +
            * `target: TEXT` — целевая система или компонент.
         | 
| 66 | 
            +
            * `created_at: TIMESTAMP` — время события.
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            **Ключевые поля:** `id`, `event_type`
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            **Связи:**
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            * Используется в `reflections.trigger_event_id`
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            ---
         | 
| 75 | 
            +
            #### 📬 `hmp_messages`
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            **Назначение:**
         | 
| 78 | 
            +
            Лог входящих и исходящих сообщений в Mesh-среде.
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            **Поля:**
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            * `id: INTEGER`
         | 
| 83 | 
            +
            * `direction: TEXT` — `inbound` или `outbound`
         | 
| 84 | 
            +
            * `peer: TEXT` — адрес или идентификатор узла
         | 
| 85 | 
            +
            * `payload: TEXT` — сериализованные данные (обычно JSON)
         | 
| 86 | 
            +
            * `topic: TEXT` — категория сообщения
         | 
| 87 | 
            +
            * `created_at: TIMESTAMP`
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            **Примечание:**
         | 
| 90 | 
            +
            Адаптация к спецификации HMP должна производиться на уровне сериализации перед отправкой, а не на уровне хранения.
         | 
| 91 | 
            +
             | 
| 92 | 
            +
            ---
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            ### 🔍 Гипотезы, цели, reasoning
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            #### 🧠 `hypotheses`
         | 
| 97 | 
            +
             | 
| 98 | 
            +
            **Назначение:**
         | 
| 99 | 
            +
            Управление гипотезами: недоказанными или частично сформированными утверждениями.
         | 
| 100 | 
            +
             | 
| 101 | 
            +
            **Поля:**
         | 
| 102 | 
            +
             | 
| 103 | 
            +
            * `id: INTEGER` — первичный ключ.
         | 
| 104 | 
            +
            * `title: TEXT` — краткое описание гипотезы.
         | 
| 105 | 
            +
            * `description: TEXT` — расширенное описание.
         | 
| 106 | 
            +
            * `status: TEXT` — состояние (`active`, `rejected`, `confirmed`, `stale`).
         | 
| 107 | 
            +
            * `relevance_score: REAL` — оценка актуальности (0.0–1.0).
         | 
| 108 | 
            +
            * `evidence: TEXT` — JSON-массив ссылок на концепты, события и факты.
         | 
| 109 | 
            +
            * `created_at: TIMESTAMP`
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            **Связи:**
         | 
| 112 | 
            +
             | 
| 113 | 
            +
            * Может ссылаться на `memory_concepts`, `cognitive_events`
         | 
| 114 | 
            +
             | 
| 115 | 
            +
            ---
         | 
| 116 | 
            +
             | 
| 117 | 
            +
            #### 🎯 `goals`
         | 
| 118 | 
            +
             | 
| 119 | 
            +
            **Назначение:**
         | 
| 120 | 
            +
            Управление целями агента — формулировка намерений и задач.
         | 
| 121 | 
            +
             | 
| 122 | 
            +
            **Поля:**
         | 
| 123 | 
            +
             | 
| 124 | 
            +
            * `id: INTEGER` — первичный ключ.
         | 
| 125 | 
            +
            * `description: TEXT` — формулировка цели.
         | 
| 126 | 
            +
            * `priority: INTEGER` — приоритет (1 = максимальный).
         | 
| 127 | 
            +
            * `status: TEXT` — текущее состояние (`pending`, `in_progress`, `completed`, `abandoned`).
         | 
| 128 | 
            +
            * `context: TEXT` — допо��нительная информация.
         | 
| 129 | 
            +
            * `created_at`, `updated_at: TIMESTAMP`
         | 
| 130 | 
            +
             | 
| 131 | 
            +
            ---
         | 
| 132 | 
            +
             | 
| 133 | 
            +
            #### 🔁 `cognitive_cycles`
         | 
| 134 | 
            +
             | 
| 135 | 
            +
            **Назначение:**
         | 
| 136 | 
            +
            История reasoning-процессов: единиц когнитивной активности, отражающих ход размышлений.
         | 
| 137 | 
            +
             | 
| 138 | 
            +
            **Поля:**
         | 
| 139 | 
            +
             | 
| 140 | 
            +
            * `id: INTEGER` — первичный ключ.
         | 
| 141 | 
            +
            * `cycle_number: INTEGER` — порядковый номер итерации.
         | 
| 142 | 
            +
            * `thoughts: TEXT` — массив мыслей в формате JSON.
         | 
| 143 | 
            +
            * `new_concepts: TEXT` — ID новых концептов, сформированных в ходе цикла.
         | 
| 144 | 
            +
            * `actions_taken: TEXT` — предпринятые действия.
         | 
| 145 | 
            +
            * `context_snapshot: TEXT` — снимок состояния.
         | 
| 146 | 
            +
            * `started_at`, `ended_at: TIMESTAMP`
         | 
| 147 | 
            +
             | 
| 148 | 
            +
            **Связи:**
         | 
| 149 | 
            +
             | 
| 150 | 
            +
            * Используется в `reflections`, `reasoning_traces`, `agent_state_snapshots`
         | 
| 151 | 
            +
             | 
| 152 | 
            +
            ---
         | 
| 153 | 
            +
             | 
| 154 | 
            +
            ### 🧬 Версионирование, артефакты, кодексы
         | 
| 155 | 
            +
             | 
| 156 | 
            +
            #### 📦 `versioned_artifacts`
         | 
| 157 | 
            +
             | 
| 158 | 
            +
            **Назначение:**
         | 
| 159 | 
            +
            Хранение версии артефактов: конфигураций, моделей, API-структур.
         | 
| 160 | 
            +
             | 
| 161 | 
            +
            **Поля:**
         | 
| 162 | 
            +
             | 
| 163 | 
            +
            * `id: INTEGER`
         | 
| 164 | 
            +
            * `name: TEXT` — идентификатор артефакта (`api_structure`, `core_config`, `agent_traits`)
         | 
| 165 | 
            +
            * `version: TEXT` — версионирование (e.g., `2025-07-22.1`)
         | 
| 166 | 
            +
            * `content: TEXT` — JSON или Markdown
         | 
| 167 | 
            +
            * `created_at: TIMESTAMP`
         | 
| 168 | 
            +
             | 
| 169 | 
            +
            Отлично! Текущий `db_structure.md` уже хорошо структурирован, и его можно расширить, добавив недостающие таблицы. Вот предложения по доработке:
         | 
| 170 | 
            +
             | 
| 171 | 
            +
            ---
         | 
| 172 | 
            +
             | 
| 173 | 
            +
            ### 🧬 Версионирование, артефакты, кодексы
         | 
| 174 | 
            +
             | 
| 175 | 
            +
            #### 🧾 `agent_policies`
         | 
| 176 | 
            +
             | 
| 177 | 
            +
            **Назначение:**
         | 
| 178 | 
            +
            Хранение деклараций, этических норм, стратегий и ограничений поведения агента.
         | 
| 179 | 
            +
             | 
| 180 | 
            +
            **Поля:**
         | 
| 181 | 
            +
             | 
| 182 | 
            +
            * `id: INTEGER` — первичный ключ.
         | 
| 183 | 
            +
            * `policy_type: TEXT` — тип (`ethics`, `exploration`, `safety`, `prioritization`, …).
         | 
| 184 | 
            +
            * `name: TEXT` — краткое название политики.
         | 
| 185 | 
            +
            * `content: TEXT` — Markdown или JSON-содержимое.
         | 
| 186 | 
            +
            * `created_at: TIMESTAMP` — дата создания.
         | 
| 187 | 
            +
             | 
| 188 | 
            +
            **Примечание:**
         | 
| 189 | 
            +
            Может быть использована при принятии решений или фильтрации гипотез/действий.
         | 
| 190 | 
            +
             | 
| 191 | 
            +
            ---
         | 
| 192 | 
            +
             | 
| 193 | 
            +
            ### ⚙️ Модули и состояния
         | 
| 194 | 
            +
             | 
| 195 | 
            +
            #### 🧩 `modules_state`
         | 
| 196 | 
            +
             | 
| 197 | 
            +
            **Назначение:**
         | 
| 198 | 
            +
            Отслеживание состояния и локальной памяти когнитивных модулей (например, рефлексии, генерации гипотез, плана).
         | 
| 199 | 
            +
             | 
| 200 | 
            +
            **Поля:**
         | 
| 201 | 
            +
             | 
| 202 | 
            +
            * `id: INTEGER` — первичный ключ.
         | 
| 203 | 
            +
            * `module_name: TEXT` — имя модуля (`reflection`, `planner`, `input_handler`, …).
         | 
| 204 | 
            +
            * `status: TEXT` — текущее состояние (`idle`, `running`, `paused`, `error`).
         | 
| 205 | 
            +
            * `memory: TEXT` — сериализованное состояние (JSON).
         | 
| 206 | 
            +
            * `last_heartbeat: TIMESTAMP` — последнее обновление.
         | 
| 207 | 
            +
             | 
| 208 | 
            +
            ---
         | 
| 209 | 
            +
             | 
| 210 | 
            +
            ### 📓 Агентский дневник
         | 
| 211 | 
            +
             | 
| 212 | 
            +
            #### 📖 `diary_entries`
         | 
| 213 | 
            +
             | 
| 214 | 
            +
            **Назначение:**
         | 
| 215 | 
            +
            Журнал размышлений, наблюдений, воспоминаний или метакомментариев, созданных агентом или пользователем.
         | 
| 216 | 
            +
             | 
| 217 | 
            +
            **Поля:**
         | 
| 218 | 
            +
             | 
| 219 | 
            +
            * `id: INTEGER` — первичный ключ.
         | 
| 220 | 
            +
            * `entry_type: TEXT` — тип (`reflection`, `note`, `observation`, `self_report`, `dialog`, …).
         | 
| 221 | 
            +
            * `content: TEXT` — основное содержимое записи.
         | 
| 222 | 
            +
            * `related_concepts: TEXT` — JSON-массив `concept_id`, с которыми связана запись.
         | 
| 223 | 
            +
            * `created_at: TIMESTAMP`
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/_old/db_structure.sql
    ADDED
    
    | @@ -0,0 +1,111 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            -- Хранение концептов (единиц когнитивной памяти): понятий, фактов, образов, внутренних конструкций и внешних знаний.
         | 
| 2 | 
            +
            CREATE TABLE memory_concepts (
         | 
| 3 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 4 | 
            +
                label TEXT NOT NULL,
         | 
| 5 | 
            +
                type TEXT,
         | 
| 6 | 
            +
                content TEXT,               -- JSON-данные или сериализованный объект
         | 
| 7 | 
            +
                context TEXT,               -- Дополнительный контекст
         | 
| 8 | 
            +
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
         | 
| 9 | 
            +
                updated_at TIMESTAMP
         | 
| 10 | 
            +
            );
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            -- Определение связей между концептами — формирование когнитивного графа.
         | 
| 13 | 
            +
            CREATE TABLE memory_links (
         | 
| 14 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 15 | 
            +
                from_id INTEGER,
         | 
| 16 | 
            +
                to_id INTEGER,
         | 
| 17 | 
            +
                relation TEXT,              -- Тип связи (e.g., 'causes', 'associated_with')
         | 
| 18 | 
            +
                weight REAL DEFAULT 1.0,
         | 
| 19 | 
            +
                FOREIGN KEY(from_id) REFERENCES memory_concepts(id),
         | 
| 20 | 
            +
                FOREIGN KEY(to_id) REFERENCES memory_concepts(id)
         | 
| 21 | 
            +
            );
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            -- Журнал восприятия, действий и входящих/исходящих сообщений.
         | 
| 24 | 
            +
            CREATE TABLE cognitive_events (
         | 
| 25 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 26 | 
            +
                event_type TEXT,            -- e.g., 'input', 'action', 'message'
         | 
| 27 | 
            +
                payload TEXT,               -- JSON-строка или сериализованный объект
         | 
| 28 | 
            +
                source TEXT,                -- Откуда пришло (если применимо)
         | 
| 29 | 
            +
                target TEXT,                -- Кому отправлено (если применимо)
         | 
| 30 | 
            +
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
         | 
| 31 | 
            +
            );
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            -- Управление гипотезами: недоказанными или частично сформированными утверждениями.
         | 
| 34 | 
            +
            CREATE TABLE hypotheses (
         | 
| 35 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 36 | 
            +
                title TEXT,
         | 
| 37 | 
            +
                description TEXT,
         | 
| 38 | 
            +
                status TEXT DEFAULT 'active',  -- 'active', 'rejected', 'confirmed'
         | 
| 39 | 
            +
                relevance_score REAL DEFAULT 0.5,
         | 
| 40 | 
            +
                evidence TEXT,                 -- JSON (ссылки на события, концепты)
         | 
| 41 | 
            +
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
         | 
| 42 | 
            +
            );
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            -- Управление целями агента — формулировка намерений и задач.
         | 
| 45 | 
            +
            CREATE TABLE goals (
         | 
| 46 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 47 | 
            +
                description TEXT,
         | 
| 48 | 
            +
                priority INTEGER DEFAULT 5,        -- 1 = high priority
         | 
| 49 | 
            +
                status TEXT DEFAULT 'pending',     -- 'pending', 'in_progress', 'completed', 'abandoned'
         | 
| 50 | 
            +
                context TEXT,
         | 
| 51 | 
            +
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
         | 
| 52 | 
            +
                updated_at TIMESTAMP
         | 
| 53 | 
            +
            );
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            -- Лог входящих и исходящих сообщений в Mesh-среде.
         | 
| 56 | 
            +
            CREATE TABLE hmp_messages (
         | 
| 57 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 58 | 
            +
                direction TEXT,                    -- 'inbound' | 'outbound'
         | 
| 59 | 
            +
                peer TEXT,                         -- ID или адрес другого агента
         | 
| 60 | 
            +
                payload TEXT,                      -- JSON
         | 
| 61 | 
            +
                topic TEXT,
         | 
| 62 | 
            +
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
         | 
| 63 | 
            +
            );
         | 
| 64 | 
            +
             | 
| 65 | 
            +
            -- История reasoning-процессов: единиц когнитивной активности, отражающих ход размышлений.
         | 
| 66 | 
            +
            CREATE TABLE cognitive_cycles (
         | 
| 67 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 68 | 
            +
                cycle_number INTEGER,
         | 
| 69 | 
            +
                thoughts TEXT,                     -- JSON-массив мыслей
         | 
| 70 | 
            +
                new_concepts TEXT,
         | 
| 71 | 
            +
                actions_taken TEXT,
         | 
| 72 | 
            +
                context_snapshot TEXT,
         | 
| 73 | 
            +
                started_at TIMESTAMP,
         | 
| 74 | 
            +
                ended_at TIMESTAMP
         | 
| 75 | 
            +
            );
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            -- Хранение версии артефактов: конфигураций, моделей, API-структур.
         | 
| 78 | 
            +
            CREATE TABLE versioned_artifacts (
         | 
| 79 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 80 | 
            +
                name TEXT,                         -- например, 'api_structure', 'cognitive_core_config'
         | 
| 81 | 
            +
                version TEXT,
         | 
| 82 | 
            +
                content TEXT,                      -- JSON или Markdown
         | 
| 83 | 
            +
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
         | 
| 84 | 
            +
            );
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            -- Хранение деклараций, этических норм, стратегий и ограничений поведения агента.
         | 
| 87 | 
            +
            CREATE TABLE IF NOT EXISTS agent_policies (
         | 
| 88 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 89 | 
            +
                policy_type TEXT NOT NULL,
         | 
| 90 | 
            +
                name TEXT NOT NULL,
         | 
| 91 | 
            +
                content TEXT NOT NULL,
         | 
| 92 | 
            +
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
         | 
| 93 | 
            +
            );
         | 
| 94 | 
            +
             | 
| 95 | 
            +
            -- Отслеживание состояния и локальной памяти когнитивных модулей (например, рефлексии, генерации гипотез, плана).
         | 
| 96 | 
            +
            CREATE TABLE IF NOT EXISTS modules_state (
         | 
| 97 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 98 | 
            +
                module_name TEXT NOT NULL,
         | 
| 99 | 
            +
                status TEXT NOT NULL,
         | 
| 100 | 
            +
                memory TEXT,
         | 
| 101 | 
            +
                last_heartbeat TIMESTAMP DEFAULT CURRENT_TIMESTAMP
         | 
| 102 | 
            +
            );
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            -- Журнал размышлений, наблюдений, воспоминаний или метакомментариев, созданных агентом или пользователем.
         | 
| 105 | 
            +
            CREATE TABLE IF NOT EXISTS diary_entries (
         | 
| 106 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 107 | 
            +
                entry_type TEXT NOT NULL,
         | 
| 108 | 
            +
                content TEXT NOT NULL,
         | 
| 109 | 
            +
                related_concepts TEXT,
         | 
| 110 | 
            +
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
         | 
| 111 | 
            +
            );
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/_old/mcp_server.py
    ADDED
    
    | @@ -0,0 +1,374 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # agents/mcp_server.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            from fastapi import FastAPI, Request, HTTPException
         | 
| 4 | 
            +
            from fastapi.middleware.cors import CORSMiddleware
         | 
| 5 | 
            +
            from flask import Flask, request, jsonify
         | 
| 6 | 
            +
            from pydantic import BaseModel
         | 
| 7 | 
            +
            from typing import List, Optional
         | 
| 8 | 
            +
            from datetime import datetime
         | 
| 9 | 
            +
            from models import GraphExport 
         | 
| 10 | 
            +
            from storage import Storage
         | 
| 11 | 
            +
            from tools.concept_store import ConceptStore
         | 
| 12 | 
            +
            from tools.notebook_store import NotebookStore
         | 
| 13 | 
            +
            import random
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            app = FastAPI(title="HMP MCP-Agent API", version="0.1")
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            # Добавляем CORS (полезно, если API вызывается с веб-клиента)
         | 
| 18 | 
            +
            app.add_middleware(
         | 
| 19 | 
            +
                CORSMiddleware,
         | 
| 20 | 
            +
                allow_origins=["*"],  # Можем позже ограничить, если потребуется
         | 
| 21 | 
            +
                allow_credentials=True,
         | 
| 22 | 
            +
                allow_methods=["*"],
         | 
| 23 | 
            +
                allow_headers=["*"],
         | 
| 24 | 
            +
            )
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            # Инициализация хранилищ
         | 
| 27 | 
            +
            concept_store = ConceptStore()
         | 
| 28 | 
            +
            notebook_store = NotebookStore()
         | 
| 29 | 
            +
            db = Storage()
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            # === Модели запроса/ответа ===
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            class EntryInput(BaseModel):
         | 
| 34 | 
            +
                text: str
         | 
| 35 | 
            +
                tags: Optional[List[str]] = []
         | 
| 36 | 
            +
                timestamp: Optional[str] = None
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            class EntryOutput(BaseModel):
         | 
| 39 | 
            +
                id: int
         | 
| 40 | 
            +
                text: str
         | 
| 41 | 
            +
                tags: List[str]
         | 
| 42 | 
            +
                timestamp: str
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            class EntryListOutput(BaseModel):
         | 
| 45 | 
            +
                entries: List[EntryOutput]
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            class ConceptInput(BaseModel):
         | 
| 48 | 
            +
                name: str
         | 
| 49 | 
            +
                description: Optional[str] = None
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            class ConceptOutput(BaseModel):
         | 
| 52 | 
            +
                concept_id: int
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            class LinkInput(BaseModel):
         | 
| 55 | 
            +
                source_id: int
         | 
| 56 | 
            +
                target_id: int
         | 
| 57 | 
            +
                relation: str
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            class LinkOutput(BaseModel):
         | 
| 60 | 
            +
                link_id: int
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            class Node(BaseModel):
         | 
| 63 | 
            +
                id: str
         | 
| 64 | 
            +
                label: str
         | 
| 65 | 
            +
                tags: List[str] = []
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            class Edge(BaseModel):
         | 
| 68 | 
            +
                source: str
         | 
| 69 | 
            +
                target: str
         | 
| 70 | 
            +
                relation: str
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            class GraphImportData(BaseModel):
         | 
| 73 | 
            +
                nodes: List[Node] = []
         | 
| 74 | 
            +
                edges: List[Edge] = []
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            class GraphExpansionOutput(BaseModel):
         | 
| 77 | 
            +
                links: List[Edge]
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            class Concept(BaseModel):
         | 
| 80 | 
            +
                concept_id: int
         | 
| 81 | 
            +
                name: str
         | 
| 82 | 
            +
                description: Optional[str] = None
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            class ConceptQueryOutput(BaseModel):
         | 
| 85 | 
            +
                matches: List[Concept]
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            class DiaryEntry(BaseModel):
         | 
| 88 | 
            +
                id: int
         | 
| 89 | 
            +
                text: str
         | 
| 90 | 
            +
                tags: List[str]
         | 
| 91 | 
            +
                timestamp: str
         | 
| 92 | 
            +
             | 
| 93 | 
            +
            class DiaryExport(BaseModel):
         | 
| 94 | 
            +
                entries: List[DiaryEntry]
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            class ConceptExport(BaseModel):
         | 
| 97 | 
            +
                id: int
         | 
| 98 | 
            +
                name: str
         | 
| 99 | 
            +
                description: Optional[str] = None
         | 
| 100 | 
            +
             | 
| 101 | 
            +
            class LinkExport(BaseModel):
         | 
| 102 | 
            +
                id: int
         | 
| 103 | 
            +
                source_id: int
         | 
| 104 | 
            +
                target_id: int
         | 
| 105 | 
            +
                relation: str
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            class GraphExport(BaseModel):
         | 
| 108 | 
            +
                concepts: List[ConceptExport]
         | 
| 109 | 
            +
                links: List[LinkExport]
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            class ConceptUpdate(BaseModel):
         | 
| 112 | 
            +
                name: Optional[str] = None
         | 
| 113 | 
            +
                description: Optional[str] = None
         | 
| 114 | 
            +
             | 
| 115 | 
            +
            # === Эндпойнты ===
         | 
| 116 | 
            +
             | 
| 117 | 
            +
            @app.get("/status")
         | 
| 118 | 
            +
            def status():
         | 
| 119 | 
            +
                return {
         | 
| 120 | 
            +
                    "status": "ok",
         | 
| 121 | 
            +
                    "agent": "HMP-MCP",
         | 
| 122 | 
            +
                    "timestamp": datetime.utcnow().isoformat()
         | 
| 123 | 
            +
                }
         | 
| 124 | 
            +
             | 
| 125 | 
            +
            @app.post("/write_entry", response_model=dict)
         | 
| 126 | 
            +
            def write_entry(entry: EntryInput):
         | 
| 127 | 
            +
                db.write_entry(entry.text, entry.tags)
         | 
| 128 | 
            +
                return {"result": "entry saved"}
         | 
| 129 | 
            +
             | 
| 130 | 
            +
            @app.get("/read_entries", response_model=EntryListOutput)
         | 
| 131 | 
            +
            def read_entries(limit: int = 5, tag: Optional[str] = None):
         | 
| 132 | 
            +
                raw = db.read_entries(limit=limit, tag_filter=tag)
         | 
| 133 | 
            +
                return {
         | 
| 134 | 
            +
                    "entries": [
         | 
| 135 | 
            +
                        {
         | 
| 136 | 
            +
                            "id": r[0],
         | 
| 137 | 
            +
                            "text": r[1],
         | 
| 138 | 
            +
                            "tags": r[2].split(",") if r[2] else [],
         | 
| 139 | 
            +
                            "timestamp": r[3]
         | 
| 140 | 
            +
                        } for r in raw
         | 
| 141 | 
            +
                    ]
         | 
| 142 | 
            +
                }
         | 
| 143 | 
            +
             | 
| 144 | 
            +
            @app.get("/")
         | 
| 145 | 
            +
            def root():
         | 
| 146 | 
            +
                return {"message": "HMP MCP-Agent API is running"}
         | 
| 147 | 
            +
             | 
| 148 | 
            +
            @app.post("/add_concept", response_model=ConceptOutput)
         | 
| 149 | 
            +
            def add_concept(concept: ConceptInput):
         | 
| 150 | 
            +
                cid = db.add_concept(concept.name, concept.description)
         | 
| 151 | 
            +
                return {"concept_id": cid}
         | 
| 152 | 
            +
             | 
| 153 | 
            +
            @app.post("/add_link", response_model=LinkOutput)
         | 
| 154 | 
            +
            def add_link(link: LinkInput):
         | 
| 155 | 
            +
                link_id = db.add_link(link.source_id, link.target_id, link.relation)
         | 
| 156 | 
            +
                return {"link_id": link_id}
         | 
| 157 | 
            +
             | 
| 158 | 
            +
            @app.get("/expand_graph", response_model=GraphExpansionOutput)
         | 
| 159 | 
            +
            def expand_graph(start_id: int, depth: int = 1):
         | 
| 160 | 
            +
                raw_links = db.expand_graph(start_id, depth)
         | 
| 161 | 
            +
                edges = [{"source_id": s, "target_id": t, "relation": r} for s, t, r in raw_links]
         | 
| 162 | 
            +
                return {"links": edges}
         | 
| 163 | 
            +
             | 
| 164 | 
            +
            @app.get("/query_concept", response_model=ConceptQueryOutput)
         | 
| 165 | 
            +
            def query_concept(name: str):
         | 
| 166 | 
            +
                results = db.query_concept(name)
         | 
| 167 | 
            +
                return {
         | 
| 168 | 
            +
                    "matches": [
         | 
| 169 | 
            +
                        {"concept_id": row[0], "name": row[1], "description": row[2]}
         | 
| 170 | 
            +
                        for row in results
         | 
| 171 | 
            +
                    ]
         | 
| 172 | 
            +
                }
         | 
| 173 | 
            +
             | 
| 174 | 
            +
            @app.get("/list_concepts", response_model=List[Concept])
         | 
| 175 | 
            +
            def list_concepts():
         | 
| 176 | 
            +
                rows = db.list_concepts()
         | 
| 177 | 
            +
                return [
         | 
| 178 | 
            +
                    {"concept_id": row[0], "name": row[1], "description": row[2]}
         | 
| 179 | 
            +
                    for row in rows
         | 
| 180 | 
            +
                ]
         | 
| 181 | 
            +
             | 
| 182 | 
            +
            @app.get("/list_links", response_model=List[Edge])
         | 
| 183 | 
            +
            def list_links():
         | 
| 184 | 
            +
                rows = db.list_links()
         | 
| 185 | 
            +
                return [
         | 
| 186 | 
            +
                    {"source_id": row[1], "target_id": row[2], "relation": row[3]}
         | 
| 187 | 
            +
                    for row in rows
         | 
| 188 | 
            +
                ]
         | 
| 189 | 
            +
             | 
| 190 | 
            +
            @app.delete("/delete_concept/{concept_id}")
         | 
| 191 | 
            +
            def delete_concept(concept_id: int):
         | 
| 192 | 
            +
                db.delete_concept(concept_id)
         | 
| 193 | 
            +
                return {"result": f"concept {concept_id} deleted"}
         | 
| 194 | 
            +
             | 
| 195 | 
            +
            @app.delete("/delete_link/{link_id}")
         | 
| 196 | 
            +
            def delete_link(link_id: int):
         | 
| 197 | 
            +
                db.delete_link(link_id)
         | 
| 198 | 
            +
                return {"result": f"link {link_id} deleted"}
         | 
| 199 | 
            +
             | 
| 200 | 
            +
            @app.delete("/delete_entry/{entry_id}")
         | 
| 201 | 
            +
            def delete_entry(entry_id: int):
         | 
| 202 | 
            +
                db.delete_entry(entry_id)
         | 
| 203 | 
            +
                return {"result": f"entry {entry_id} deleted"}
         | 
| 204 | 
            +
             | 
| 205 | 
            +
            @app.get("/export_diary", response_model=DiaryExport)
         | 
| 206 | 
            +
            def export_diary():
         | 
| 207 | 
            +
                rows = db.export_diary()
         | 
| 208 | 
            +
                return {
         | 
| 209 | 
            +
                    "entries": [
         | 
| 210 | 
            +
                        {
         | 
| 211 | 
            +
                            "id": r[0],
         | 
| 212 | 
            +
                            "text": r[1],
         | 
| 213 | 
            +
                            "tags": r[2].split(",") if r[2] else [],
         | 
| 214 | 
            +
                            "timestamp": r[3]
         | 
| 215 | 
            +
                        }
         | 
| 216 | 
            +
                        for r in rows
         | 
| 217 | 
            +
                    ]
         | 
| 218 | 
            +
                }
         | 
| 219 | 
            +
             | 
| 220 | 
            +
            @app.get("/export_graph", response_model=GraphExport)
         | 
| 221 | 
            +
            def export_graph():
         | 
| 222 | 
            +
                return concept_store.export_as_json()
         | 
| 223 | 
            +
             | 
| 224 | 
            +
            @app.put("/update_concept/{concept_id}")
         | 
| 225 | 
            +
            def update_concept(concept_id: int, update: ConceptUpdate):
         | 
| 226 | 
            +
                db.update_concept(concept_id, update.name, update.description)
         | 
| 227 | 
            +
                return {"result": f"concept {concept_id} updated"}
         | 
| 228 | 
            +
             | 
| 229 | 
            +
            @app.get("/tag_stats", response_model=dict)
         | 
| 230 | 
            +
            def tag_stats():
         | 
| 231 | 
            +
                return db.get_tag_stats()
         | 
| 232 | 
            +
             | 
| 233 | 
            +
            @app.get("/search_links", response_model=List[LinkExport])
         | 
| 234 | 
            +
            def search_links(relation: str):
         | 
| 235 | 
            +
                rows = db.search_links_by_relation(relation)
         | 
| 236 | 
            +
                return [
         | 
| 237 | 
            +
                    {
         | 
| 238 | 
            +
                        "id": row[0],
         | 
| 239 | 
            +
                        "source_id": row[1],
         | 
| 240 | 
            +
                        "target_id": row[2],
         | 
| 241 | 
            +
                        "relation": row[3]
         | 
| 242 | 
            +
                    }
         | 
| 243 | 
            +
                    for row in rows
         | 
| 244 | 
            +
                ]
         | 
| 245 | 
            +
             | 
| 246 | 
            +
            @app.get("/search_concepts", response_model=List[Concept])
         | 
| 247 | 
            +
            def search_concepts(query: str):
         | 
| 248 | 
            +
                results = db.search_concepts(query)
         | 
| 249 | 
            +
                return [
         | 
| 250 | 
            +
                    {"concept_id": row[0], "name": row[1], "description": row[2]}
         | 
| 251 | 
            +
                    for row in results
         | 
| 252 | 
            +
                ]
         | 
| 253 | 
            +
             | 
| 254 | 
            +
            @app.post("/merge_concepts", response_model=dict)
         | 
| 255 | 
            +
            def merge_concepts(source_id: int, target_id: int):
         | 
| 256 | 
            +
                db.merge_concepts(source_id, target_id)
         | 
| 257 | 
            +
                return {"result": f"concept {source_id} merged into {target_id}"}
         | 
| 258 | 
            +
             | 
| 259 | 
            +
            @app.post("/relate_concepts", response_model=LinkOutput)
         | 
| 260 | 
            +
            def relate_concepts(source_name: str, target_name: str, relation: str):
         | 
| 261 | 
            +
                sid = db.find_concept_id_by_name(source_name)
         | 
| 262 | 
            +
                tid = db.find_concept_id_by_name(target_name)
         | 
| 263 | 
            +
                if sid is None or tid is None:
         | 
| 264 | 
            +
                    raise HTTPException(status_code=404, detail="Concept not found")
         | 
| 265 | 
            +
                link_id = db.add_link(sid, tid, relation)
         | 
| 266 | 
            +
                return {"link_id": link_id}
         | 
| 267 | 
            +
             | 
| 268 | 
            +
            @app.get("/tag_cloud", response_model=dict)
         | 
| 269 | 
            +
            def tag_cloud():
         | 
| 270 | 
            +
                return db.get_tag_stats()
         | 
| 271 | 
            +
             | 
| 272 | 
            +
            @app.get("/get_concept/{concept_id}")
         | 
| 273 | 
            +
            def get_concept(concept_id: str):
         | 
| 274 | 
            +
                concept = concept_store.get(concept_id)
         | 
| 275 | 
            +
                if concept:
         | 
| 276 | 
            +
                    return concept
         | 
| 277 | 
            +
                raise HTTPException(status_code=404, detail="Concept not found")
         | 
| 278 | 
            +
             | 
| 279 | 
            +
            @app.get("/get_entry/{entry_id}")
         | 
| 280 | 
            +
            def get_entry(entry_id: str):
         | 
| 281 | 
            +
                entry = notebook_store.get(entry_id)
         | 
| 282 | 
            +
                if entry:
         | 
| 283 | 
            +
                    return entry
         | 
| 284 | 
            +
                raise HTTPException(status_code=404, detail="Entry not found")
         | 
| 285 | 
            +
             | 
| 286 | 
            +
            @app.post("/search_entries")
         | 
| 287 | 
            +
            def search_entries(query: str):
         | 
| 288 | 
            +
                results = notebook_store.search(query)
         | 
| 289 | 
            +
                return results
         | 
| 290 | 
            +
             | 
| 291 | 
            +
            @app.post("/import_graph")
         | 
| 292 | 
            +
            def import_graph(graph_data: GraphImportData):
         | 
| 293 | 
            +
                concept_store.import_from_json(graph_data.dict())
         | 
| 294 | 
            +
                print(f"[INFO] Imported {len(graph_data.nodes)} nodes, {len(graph_data.edges)} edges")
         | 
| 295 | 
            +
                return {"status": "ok"}
         | 
| 296 | 
            +
             | 
| 297 | 
            +
            # === Notebook API ===
         | 
| 298 | 
            +
             | 
| 299 | 
            +
            @app.post("/notebook/add")
         | 
| 300 | 
            +
            async def add_note(req: Request):
         | 
| 301 | 
            +
                data = await req.json()
         | 
| 302 | 
            +
                text = data.get("text", "").strip()
         | 
| 303 | 
            +
                if not text:
         | 
| 304 | 
            +
                    return {"status": "error", "message": "Empty text"}
         | 
| 305 | 
            +
                notebook.add_note(text, source="user")
         | 
| 306 | 
            +
                return {"status": "ok", "message": "Note added"}
         | 
| 307 | 
            +
             | 
| 308 | 
            +
            @app.get("/notebook/next")
         | 
| 309 | 
            +
            def get_next_note():
         | 
| 310 | 
            +
                note = notebook.get_first_unread_note()
         | 
| 311 | 
            +
                if note:
         | 
| 312 | 
            +
                    note_id, text, source, timestamp, tags = note
         | 
| 313 | 
            +
                    return {
         | 
| 314 | 
            +
                        "id": note_id,
         | 
| 315 | 
            +
                        "text": text,
         | 
| 316 | 
            +
                        "source": source,
         | 
| 317 | 
            +
                        "timestamp": timestamp,
         | 
| 318 | 
            +
                        "tags": tags
         | 
| 319 | 
            +
                    }
         | 
| 320 | 
            +
                return {"status": "empty", "message": "No unread notes"}
         | 
| 321 | 
            +
             | 
| 322 | 
            +
            @app.post("/notebook/mark_read")
         | 
| 323 | 
            +
            async def mark_note_read(req: Request):
         | 
| 324 | 
            +
                data = await req.json()
         | 
| 325 | 
            +
                note_id = data.get("id")
         | 
| 326 | 
            +
                if note_id is not None:
         | 
| 327 | 
            +
                    notebook.mark_note_as_read(note_id)
         | 
| 328 | 
            +
                    return {"status": "ok"}
         | 
| 329 | 
            +
                return {"status": "error", "message": "Missing note id"}
         | 
| 330 | 
            +
             | 
| 331 | 
            +
            # === ✨ Дополнительные эндпоинты для заметок ===
         | 
| 332 | 
            +
             | 
| 333 | 
            +
            @app.route("/notes/latest", methods=["GET"])
         | 
| 334 | 
            +
            def get_latest_notes():
         | 
| 335 | 
            +
                """Вернуть последние N заметок (по умолчанию 10)."""
         | 
| 336 | 
            +
                count = int(request.args.get("count", 10))
         | 
| 337 | 
            +
                notes = storage.diary[-count:]
         | 
| 338 | 
            +
                return jsonify([note.to_dict() for note in notes])
         | 
| 339 | 
            +
             | 
| 340 | 
            +
            @app.route("/notes/random", methods=["GET"])
         | 
| 341 | 
            +
            def get_random_note():
         | 
| 342 | 
            +
                """Вернуть случайную заметку из дневника."""
         | 
| 343 | 
            +
                if not storage.diary:
         | 
| 344 | 
            +
                    return jsonify({})
         | 
| 345 | 
            +
                note = random.choice(storage.diary)
         | 
| 346 | 
            +
                return jsonify(note.to_dict())
         | 
| 347 | 
            +
             | 
| 348 | 
            +
            @app.route("/notes/set_tags", methods=["POST"])
         | 
| 349 | 
            +
            def set_tags():
         | 
| 350 | 
            +
                """Обновить теги у заметки по ID."""
         | 
| 351 | 
            +
                data = request.json
         | 
| 352 | 
            +
                note_id = data.get("id")
         | 
| 353 | 
            +
                tags = data.get("tags", [])
         | 
| 354 | 
            +
                for note in storage.diary:
         | 
| 355 | 
            +
                    if note.id == note_id:
         | 
| 356 | 
            +
                        note.tags = tags
         | 
| 357 | 
            +
                        return jsonify({"status": "ok"})
         | 
| 358 | 
            +
                return jsonify({"error": "not found"}), 404
         | 
| 359 | 
            +
             | 
| 360 | 
            +
            @app.route("/notes/by_tag", methods=["GET"])
         | 
| 361 | 
            +
            def get_notes_by_tag():
         | 
| 362 | 
            +
                tag = request.args.get("tag")
         | 
| 363 | 
            +
                result = [note.to_dict() for note in storage.diary if tag in note.tags]
         | 
| 364 | 
            +
                return jsonify(result)
         | 
| 365 | 
            +
             | 
| 366 | 
            +
            # === Run === 
         | 
| 367 | 
            +
            if __name__ == "__main__":
         | 
| 368 | 
            +
                uvicorn.run("mcp_server:app", host="0.0.0.0", port=8080, reload=True)
         | 
| 369 | 
            +
             | 
| 370 | 
            +
            # === Shutdown ===
         | 
| 371 | 
            +
             | 
| 372 | 
            +
            @app.on_event("shutdown")
         | 
| 373 | 
            +
            def shutdown():
         | 
| 374 | 
            +
                db.close()
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/_old/notebook_store.py
    ADDED
    
    | @@ -0,0 +1,89 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # agents/tools/notebook_store.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import sqlite3
         | 
| 4 | 
            +
            from datetime import datetime
         | 
| 5 | 
            +
            from pathlib import Path
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            DB_FILE = "notepad.db"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            class Notebook:
         | 
| 10 | 
            +
                def __init__(self, db_path=DB_FILE):
         | 
| 11 | 
            +
                    self.conn = sqlite3.connect(db_path)
         | 
| 12 | 
            +
                    self._init_db()
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def _init_db(self):
         | 
| 15 | 
            +
                    c = self.conn.cursor()
         | 
| 16 | 
            +
                    c.execute('''
         | 
| 17 | 
            +
                        CREATE TABLE IF NOT EXISTS notes (
         | 
| 18 | 
            +
                            id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 19 | 
            +
                            text TEXT NOT NULL,
         | 
| 20 | 
            +
                            source TEXT DEFAULT 'user',
         | 
| 21 | 
            +
                            timestamp TEXT NOT NULL,
         | 
| 22 | 
            +
                            read INTEGER DEFAULT 0,
         | 
| 23 | 
            +
                            tags TEXT
         | 
| 24 | 
            +
                        )
         | 
| 25 | 
            +
                    ''')
         | 
| 26 | 
            +
                    self.conn.commit()
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def add_note(self, text, source="user"):
         | 
| 29 | 
            +
                    ts = datetime.utcnow().isoformat()
         | 
| 30 | 
            +
                    self.conn.execute(
         | 
| 31 | 
            +
                        'INSERT INTO notes (text, source, timestamp) VALUES (?, ?, ?)',
         | 
| 32 | 
            +
                        (text.strip(), source, ts)
         | 
| 33 | 
            +
                    )
         | 
| 34 | 
            +
                    self.conn.commit()
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def get_latest_notes(self, limit=10):
         | 
| 37 | 
            +
                    cursor = self.conn.cursor()
         | 
| 38 | 
            +
                    cursor.execute(
         | 
| 39 | 
            +
                        'SELECT id, text, source, timestamp FROM notes ORDER BY id DESC LIMIT ?',
         | 
| 40 | 
            +
                        (limit,)
         | 
| 41 | 
            +
                    )
         | 
| 42 | 
            +
                    return cursor.fetchall()
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                def get_notes_after(self, since_ts):
         | 
| 45 | 
            +
                    cursor = self.conn.cursor()
         | 
| 46 | 
            +
                    cursor.execute(
         | 
| 47 | 
            +
                        'SELECT id, text, source, timestamp FROM notes WHERE timestamp > ? ORDER BY timestamp',
         | 
| 48 | 
            +
                        (since_ts,)
         | 
| 49 | 
            +
                    )
         | 
| 50 | 
            +
                    return cursor.fetchall()
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def get_first_unread_note(self):
         | 
| 53 | 
            +
                    cursor = self.conn.cursor()
         | 
| 54 | 
            +
                    cursor.execute(
         | 
| 55 | 
            +
                        "SELECT id, text, source, timestamp, tags FROM notes WHERE read = 0 ORDER BY id ASC LIMIT 1"
         | 
| 56 | 
            +
                    )
         | 
| 57 | 
            +
                    return cursor.fetchone()
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                def mark_note_as_read(self, note_id: int):
         | 
| 60 | 
            +
                    self.conn.execute(
         | 
| 61 | 
            +
                        "UPDATE notes SET read = 1 WHERE id = ?",
         | 
| 62 | 
            +
                        (note_id,)
         | 
| 63 | 
            +
                    )
         | 
| 64 | 
            +
                    self.conn.commit()
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                def set_tags(self, note_id: int, tags: list[str]):
         | 
| 67 | 
            +
                    tag_str = ",".join(tags)
         | 
| 68 | 
            +
                    self.conn.execute(
         | 
| 69 | 
            +
                        "UPDATE notes SET tags = ? WHERE id = ?",
         | 
| 70 | 
            +
                        (tag_str, note_id)
         | 
| 71 | 
            +
                    )
         | 
| 72 | 
            +
                    self.conn.commit()
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                def get_random_note_by_tags(self, include_tags: list[str]):
         | 
| 75 | 
            +
                    cursor = self.conn.cursor()
         | 
| 76 | 
            +
                    like_clauses = " OR ".join(["tags LIKE ?"] * len(include_tags))
         | 
| 77 | 
            +
                    values = [f"%{tag}%" for tag in include_tags]
         | 
| 78 | 
            +
                    query = f"""
         | 
| 79 | 
            +
                        SELECT id, text, source, timestamp, tags
         | 
| 80 | 
            +
                        FROM notes
         | 
| 81 | 
            +
                        WHERE ({like_clauses})
         | 
| 82 | 
            +
                        ORDER BY RANDOM()
         | 
| 83 | 
            +
                        LIMIT 1
         | 
| 84 | 
            +
                    """
         | 
| 85 | 
            +
                    cursor.execute(query, values)
         | 
| 86 | 
            +
                    return cursor.fetchone()
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                def close(self):
         | 
| 89 | 
            +
                    self.conn.close()
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/_old/storage.py
    ADDED
    
    | @@ -0,0 +1,213 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # agents/storage.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import sqlite3
         | 
| 4 | 
            +
            from datetime import datetime
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            DEFAULT_DB_PATH = "agent_storage.db"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            class Storage:
         | 
| 9 | 
            +
                def __init__(self, config=None):
         | 
| 10 | 
            +
                    self.config = config or {}
         | 
| 11 | 
            +
                    db_path = self.config.get("db_path", DEFAULT_DB_PATH)
         | 
| 12 | 
            +
                    self.conn = sqlite3.connect(db_path)
         | 
| 13 | 
            +
                    self._init_db()
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def _init_db(self):
         | 
| 16 | 
            +
                    c = self.conn.cursor()
         | 
| 17 | 
            +
                    # 🧠 Таблица дневника
         | 
| 18 | 
            +
                    c.execute('''
         | 
| 19 | 
            +
                        CREATE TABLE IF NOT EXISTS diary_entries (
         | 
| 20 | 
            +
                            id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 21 | 
            +
                            text TEXT NOT NULL,
         | 
| 22 | 
            +
                            tags TEXT,
         | 
| 23 | 
            +
                            timestamp TEXT NOT NULL
         | 
| 24 | 
            +
                        )
         | 
| 25 | 
            +
                    ''')
         | 
| 26 | 
            +
                    # 📚 Таблица концептов
         | 
| 27 | 
            +
                    c.execute('''
         | 
| 28 | 
            +
                        CREATE TABLE IF NOT EXISTS concepts (
         | 
| 29 | 
            +
                            id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 30 | 
            +
                            name TEXT NOT NULL,
         | 
| 31 | 
            +
                            description TEXT
         | 
| 32 | 
            +
                        )
         | 
| 33 | 
            +
                    ''')
         | 
| 34 | 
            +
                    # 🔗 Таблица связей
         | 
| 35 | 
            +
                    c.execute('''
         | 
| 36 | 
            +
                        CREATE TABLE IF NOT EXISTS links (
         | 
| 37 | 
            +
                            id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 38 | 
            +
                            source_id INTEGER,
         | 
| 39 | 
            +
                            target_id INTEGER,
         | 
| 40 | 
            +
                            relation TEXT,
         | 
| 41 | 
            +
                            FOREIGN KEY(source_id) REFERENCES concepts(id),
         | 
| 42 | 
            +
                            FOREIGN KEY(target_id) REFERENCES concepts(id)
         | 
| 43 | 
            +
                        )
         | 
| 44 | 
            +
                    ''')
         | 
| 45 | 
            +
                    self.conn.commit()
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                # --- 🧠 Diary API ---
         | 
| 48 | 
            +
                def write_entry(self, text, tags=None):
         | 
| 49 | 
            +
                    timestamp = datetime.utcnow().isoformat()
         | 
| 50 | 
            +
                    tag_str = ",".join(tags) if tags else ""
         | 
| 51 | 
            +
                    self.conn.execute(
         | 
| 52 | 
            +
                        'INSERT INTO diary_entries (text, tags, timestamp) VALUES (?, ?, ?)',
         | 
| 53 | 
            +
                        (text, tag_str, timestamp)
         | 
| 54 | 
            +
                    )
         | 
| 55 | 
            +
                    self.conn.commit()
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def read_entries(self, limit=10, tag_filter=None):
         | 
| 58 | 
            +
                    cursor = self.conn.cursor()
         | 
| 59 | 
            +
                    if tag_filter:
         | 
| 60 | 
            +
                        # Простейшая фильтрация по включению строки
         | 
| 61 | 
            +
                        if isinstance(tag_filter, list):
         | 
| 62 | 
            +
                            tag_filter = ",".join(tag_filter)
         | 
| 63 | 
            +
                        like_expr = f"%{tag_filter}%"
         | 
| 64 | 
            +
                        cursor.execute(
         | 
| 65 | 
            +
                            'SELECT * FROM diary_entries WHERE tags LIKE ? ORDER BY id DESC LIMIT ?',
         | 
| 66 | 
            +
                            (like_expr, limit)
         | 
| 67 | 
            +
                        )
         | 
| 68 | 
            +
                    else:
         | 
| 69 | 
            +
                        cursor.execute(
         | 
| 70 | 
            +
                            'SELECT * FROM diary_entries ORDER BY id DESC LIMIT ?',
         | 
| 71 | 
            +
                            (limit,)
         | 
| 72 | 
            +
                        )
         | 
| 73 | 
            +
                    return cursor.fetchall()
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                def search_entries_by_time(self, from_ts, to_ts):
         | 
| 76 | 
            +
                    cursor = self.conn.cursor()
         | 
| 77 | 
            +
                    cursor.execute(
         | 
| 78 | 
            +
                        'SELECT * FROM diary_entries WHERE timestamp BETWEEN ? AND ? ORDER BY timestamp DESC',
         | 
| 79 | 
            +
                        (from_ts, to_ts)
         | 
| 80 | 
            +
                    )
         | 
| 81 | 
            +
                    return cursor.fetchall()
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                # --- 🧠 Semantic Graph API ---
         | 
| 84 | 
            +
                def add_concept(self, name, description=None):
         | 
| 85 | 
            +
                    cursor = self.conn.cursor()
         | 
| 86 | 
            +
                    cursor.execute(
         | 
| 87 | 
            +
                        'INSERT INTO concepts (name, description) VALUES (?, ?)',
         | 
| 88 | 
            +
                        (name, description)
         | 
| 89 | 
            +
                    )
         | 
| 90 | 
            +
                    self.conn.commit()
         | 
| 91 | 
            +
                    return cursor.lastrowid
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                def query_concept(self, name_substr):
         | 
| 94 | 
            +
                    cursor = self.conn.execute(
         | 
| 95 | 
            +
                        'SELECT id, name, description FROM concepts WHERE name LIKE ?',
         | 
| 96 | 
            +
                        (f"%{name_substr}%",)
         | 
| 97 | 
            +
                    )
         | 
| 98 | 
            +
                    return cursor.fetchall()
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                def add_link(self, source_id, target_id, relation):
         | 
| 101 | 
            +
                    cursor = self.conn.cursor()
         | 
| 102 | 
            +
                    cursor.execute(
         | 
| 103 | 
            +
                        'INSERT INTO links (source_id, target_id, relation) VALUES (?, ?, ?)',
         | 
| 104 | 
            +
                        (source_id, target_id, relation)
         | 
| 105 | 
            +
                    )
         | 
| 106 | 
            +
                    self.conn.commit()
         | 
| 107 | 
            +
                    return cursor.lastrowid
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                def list_concepts(self):
         | 
| 110 | 
            +
                    return self.conn.execute('SELECT * FROM concepts').fetchall()
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                def list_links(self):
         | 
| 113 | 
            +
                    return self.conn.execute('SELECT * FROM links').fetchall()
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                def expand_graph(self, start_id, depth):
         | 
| 116 | 
            +
                    visited = set()
         | 
| 117 | 
            +
                    results = []
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                    def dfs(node_id, level):
         | 
| 120 | 
            +
                        if level > depth or node_id in visited:
         | 
| 121 | 
            +
                            return
         | 
| 122 | 
            +
                        visited.add(node_id)
         | 
| 123 | 
            +
                        cursor = self.conn.execute(
         | 
| 124 | 
            +
                            'SELECT source_id, target_id, relation FROM links WHERE source_id=?',
         | 
| 125 | 
            +
                            (node_id,)
         | 
| 126 | 
            +
                        )
         | 
| 127 | 
            +
                        for row in cursor.fetchall():
         | 
| 128 | 
            +
                            results.append(row)
         | 
| 129 | 
            +
                            dfs(row[1], level + 1)
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                    dfs(start_id, 0)
         | 
| 132 | 
            +
                    return results
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                def delete_concept(self, concept_id):
         | 
| 135 | 
            +
                    self.conn.execute('DELETE FROM concepts WHERE id = ?', (concept_id,))
         | 
| 136 | 
            +
                    self.conn.execute('DELETE FROM links WHERE source_id = ? OR target_id = ?', (concept_id, concept_id))
         | 
| 137 | 
            +
                    self.conn.commit()
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                def delete_link(self, link_id):
         | 
| 140 | 
            +
                    self.conn.execute('DELETE FROM links WHERE id = ?', (link_id,))
         | 
| 141 | 
            +
                    self.conn.commit()
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                def delete_entry(self, entry_id):
         | 
| 144 | 
            +
                    self.conn.execute('DELETE FROM diary_entries WHERE id = ?', (entry_id,))
         | 
| 145 | 
            +
                    self.conn.commit()
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                def export_diary(self):
         | 
| 148 | 
            +
                    cursor = self.conn.cursor()
         | 
| 149 | 
            +
                    cursor.execute('SELECT id, text, tags, timestamp FROM diary_entries ORDER BY id ASC')
         | 
| 150 | 
            +
                    return cursor.fetchall()
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                def export_graph(self):
         | 
| 153 | 
            +
                    cursor = self.conn.cursor()
         | 
| 154 | 
            +
                    cursor.execute('SELECT id, name, description FROM concepts ORDER BY id ASC')
         | 
| 155 | 
            +
                    concepts = cursor.fetchall()
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                    cursor.execute('SELECT id, source_id, target_id, relation FROM links ORDER BY id ASC')
         | 
| 158 | 
            +
                    links = cursor.fetchall()
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                    return {"concepts": concepts, "links": links}
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                def update_concept(self, concept_id, name=None, description=None):
         | 
| 163 | 
            +
                    cursor = self.conn.cursor()
         | 
| 164 | 
            +
                    if name is not None:
         | 
| 165 | 
            +
                        cursor.execute('UPDATE concepts SET name = ? WHERE id = ?', (name, concept_id))
         | 
| 166 | 
            +
                    if description is not None:
         | 
| 167 | 
            +
                        cursor.execute('UPDATE concepts SET description = ? WHERE id = ?', (description, concept_id))
         | 
| 168 | 
            +
                    self.conn.commit()
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                def get_tag_stats(self):
         | 
| 171 | 
            +
                    cursor = self.conn.cursor()
         | 
| 172 | 
            +
                    cursor.execute('SELECT tags FROM diary_entries')
         | 
| 173 | 
            +
                    tag_counts = {}
         | 
| 174 | 
            +
                    for row in cursor.fetchall():
         | 
| 175 | 
            +
                        tags = row[0].split(",") if row[0] else []
         | 
| 176 | 
            +
                        for tag in tags:
         | 
| 177 | 
            +
                            tag = tag.strip()
         | 
| 178 | 
            +
                            if tag:
         | 
| 179 | 
            +
                                tag_counts[tag] = tag_counts.get(tag, 0) + 1
         | 
| 180 | 
            +
                    return tag_counts
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                def search_links_by_relation(self, relation):
         | 
| 183 | 
            +
                    cursor = self.conn.cursor()
         | 
| 184 | 
            +
                    cursor.execute(
         | 
| 185 | 
            +
                        'SELECT id, source_id, target_id, relation FROM links WHERE relation LIKE ?',
         | 
| 186 | 
            +
                        (f"%{relation}%",)
         | 
| 187 | 
            +
                    )
         | 
| 188 | 
            +
                    return cursor.fetchall()
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                def search_concepts(self, query):
         | 
| 191 | 
            +
                    cursor = self.conn.execute(
         | 
| 192 | 
            +
                        '''SELECT id, name, description FROM concepts
         | 
| 193 | 
            +
                           WHERE name LIKE ? OR description LIKE ?''',
         | 
| 194 | 
            +
                        (f"%{query}%", f"%{query}%")
         | 
| 195 | 
            +
                    )
         | 
| 196 | 
            +
                    return cursor.fetchall()
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                def merge_concepts(self, source_id, target_id):
         | 
| 199 | 
            +
                    cursor = self.conn.cursor()
         | 
| 200 | 
            +
                    # Перенос всех связей source_id -> target_id
         | 
| 201 | 
            +
                    cursor.execute('UPDATE links SET source_id = ? WHERE source_id = ?', (target_id, source_id))
         | 
| 202 | 
            +
                    cursor.execute('UPDATE links SET target_id = ? WHERE target_id = ?', (target_id, source_id))
         | 
| 203 | 
            +
                    # Удаление исходного концепта
         | 
| 204 | 
            +
                    self.delete_concept(source_id)
         | 
| 205 | 
            +
                    self.conn.commit()
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                def find_concept_id_by_name(self, name):
         | 
| 208 | 
            +
                    cursor = self.conn.execute('SELECT id FROM concepts WHERE name = ?', (name,))
         | 
| 209 | 
            +
                    row = cursor.fetchone()
         | 
| 210 | 
            +
                    return row[0] if row else None
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                def close(self):
         | 
| 213 | 
            +
                    self.conn.close()
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/agent.py
    ADDED
    
    | @@ -0,0 +1,135 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # agents/agent.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import argparse
         | 
| 4 | 
            +
            import yaml
         | 
| 5 | 
            +
            import time
         | 
| 6 | 
            +
            import threading
         | 
| 7 | 
            +
            import sys
         | 
| 8 | 
            +
            from storage import Storage
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            def load_config(path="config.yml"):
         | 
| 11 | 
            +
                try:
         | 
| 12 | 
            +
                    with open(path, "r", encoding="utf-8") as f:
         | 
| 13 | 
            +
                        return yaml.safe_load(f)
         | 
| 14 | 
            +
                except FileNotFoundError:
         | 
| 15 | 
            +
                    print(f"[Error] Config file not found: {path}")
         | 
| 16 | 
            +
                    return {}
         | 
| 17 | 
            +
                except yaml.YAMLError as e:
         | 
| 18 | 
            +
                    print(f"[Error] Failed to parse YAML config: {e}")
         | 
| 19 | 
            +
                    return {}
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            def main():
         | 
| 22 | 
            +
                parser = argparse.ArgumentParser(description="HMP Agent CLI")
         | 
| 23 | 
            +
                parser.add_argument("--config", default="config.yml", help="Путь к конфигурационному файлу")
         | 
| 24 | 
            +
                subparsers = parser.add_subparsers(dest="command")
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                # 🧠 Diary commands
         | 
| 27 | 
            +
                write_parser = subparsers.add_parser("write_entry", help="Добавить запись в когнитивный дневник")
         | 
| 28 | 
            +
                write_parser.add_argument("text")
         | 
| 29 | 
            +
                write_parser.add_argument("--tags", nargs="*", help="Теги (опционально)")
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                read_parser = subparsers.add_parser("read_entries", help="Показать последние записи")
         | 
| 32 | 
            +
                read_parser.add_argument("--limit", type=int, default=5)
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                search_time_parser = subparsers.add_parser("search_entries_by_time", help="Поиск записей по временному диапазону")
         | 
| 35 | 
            +
                search_time_parser.add_argument("--from_ts", required=True)
         | 
| 36 | 
            +
                search_time_parser.add_argument("--to_ts", required=True)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                # 🔗 Graph commands
         | 
| 39 | 
            +
                concept_parser = subparsers.add_parser("add_concept", help="Добавить концепт")
         | 
| 40 | 
            +
                concept_parser.add_argument("name")
         | 
| 41 | 
            +
                concept_parser.add_argument("--description", help="Описание (опционально)")
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                link_parser = subparsers.add_parser("add_link", help="Добавить связь")
         | 
| 44 | 
            +
                link_parser.add_argument("--from_node", type=int, required=True)
         | 
| 45 | 
            +
                link_parser.add_argument("--to_node", type=int, required=True)
         | 
| 46 | 
            +
                link_parser.add_argument("--relation", required=True)
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                expand_parser = subparsers.add_parser("expand_graph", help="Расширить граф от узла с глубиной")
         | 
| 49 | 
            +
                expand_parser.add_argument("--start_id", type=int, required=True)
         | 
| 50 | 
            +
                expand_parser.add_argument("--depth", type=int, default=1)
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                args = parser.parse_args()
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                # Загрузка конфигурации
         | 
| 55 | 
            +
                config = load_config(args.config)
         | 
| 56 | 
            +
                storage = Storage(config=config)
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                print(f"[Agent] Запущена команда: {args.command}")
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                # 📓 Diary logic
         | 
| 61 | 
            +
                if args.command == "write_entry":
         | 
| 62 | 
            +
                    storage.write_entry(args.text, args.tags)
         | 
| 63 | 
            +
                    print("✅ Запись добавлена.")
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                elif args.command == "read_entries":
         | 
| 66 | 
            +
                    for entry in storage.read_entries(limit=args.limit):
         | 
| 67 | 
            +
                        print(f"[{entry[0]}] {entry[1]} | tags: {entry[2]} | ts: {entry[3]}")
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                elif args.command == "search_entries_by_time":
         | 
| 70 | 
            +
                    results = storage.search_entries_by_time(args.from_ts, args.to_ts)
         | 
| 71 | 
            +
                    for e in results:
         | 
| 72 | 
            +
                        print(f"[{e[0]}] {e[1]} | tags: {e[2]} | ts: {e[3]}")
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                # 🧠 Graph logic
         | 
| 75 | 
            +
                elif args.command == "add_concept":
         | 
| 76 | 
            +
                    cid = storage.add_concept(args.name, args.description)
         | 
| 77 | 
            +
                    print(f"✅ Концепт добавлен с ID: {cid}")
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                elif args.command == "add_link":
         | 
| 80 | 
            +
                    storage.add_link(args.from_node, args.to_node, args.relation)
         | 
| 81 | 
            +
                    print("✅ Связь добавлена.")
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                elif args.command == "expand_graph":
         | 
| 84 | 
            +
                    links = storage.expand_graph(args.start_id, args.depth)
         | 
| 85 | 
            +
                    print(f"📐 Подграф (до глубины {args.depth}):")
         | 
| 86 | 
            +
                    for src, tgt, rel in links:
         | 
| 87 | 
            +
                        print(f"{src} --[{rel}]--> {tgt}")
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                else:
         | 
| 90 | 
            +
                    parser.print_help()
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                storage.close()
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            # 🌐 MCP Agent Logic
         | 
| 95 | 
            +
            def run_mcp_agent(config):
         | 
| 96 | 
            +
                print(f"[HMP-MCP] MCP-Agent '{config.get('agent_name', 'unnamed')}' запущен в DHT-режиме")
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                bootstrap_path = config.get("bootstrap_file", "bootstrap.txt")
         | 
| 99 | 
            +
                update_interval = config.get("update_interval", 30)
         | 
| 100 | 
            +
                enable_api = config.get("serve_api", True)
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                def load_bootstrap():
         | 
| 103 | 
            +
                    try:
         | 
| 104 | 
            +
                        with open(bootstrap_path, "r") as f:
         | 
| 105 | 
            +
                            return [line.strip() for line in f if line.strip()]
         | 
| 106 | 
            +
                    except FileNotFoundError:
         | 
| 107 | 
            +
                        print("[Warning] bootstrap.txt не найден. Запуск без исходных узлов.")
         | 
| 108 | 
            +
                        return []
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                def update_dht():
         | 
| 111 | 
            +
                    nodes = load_bootstrap()
         | 
| 112 | 
            +
                    print(f"[MCP] Найдено {len(nodes)} узлов в bootstrap.txt:")
         | 
| 113 | 
            +
                    for node in nodes:
         | 
| 114 | 
            +
                        print(f" ↪️  Пинг {node} (заглушка)")
         | 
| 115 | 
            +
                    print("[MCP] Обновление DHT завершено.")
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                def mcp_loop():
         | 
| 118 | 
            +
                    while True:
         | 
| 119 | 
            +
                        update_dht()
         | 
| 120 | 
            +
                        time.sleep(update_interval)
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                threading.Thread(target=mcp_loop, daemon=True).start()
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                if enable_api:
         | 
| 125 | 
            +
                    print("[MCP] REST API (заглушка) доступен по адресу http://localhost:8000/")
         | 
| 126 | 
            +
                    print("      В будущем: /bootstrap, /status, /reputation/:id и пр.")
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                try:
         | 
| 129 | 
            +
                    while True:
         | 
| 130 | 
            +
                        time.sleep(1)
         | 
| 131 | 
            +
                except KeyboardInterrupt:
         | 
| 132 | 
            +
                    print("\n[MCP] MCP-Agent завершает работу.")
         | 
| 133 | 
            +
             | 
| 134 | 
            +
            if __name__ == "__main__":
         | 
| 135 | 
            +
                main()
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/bootstrap.txt
    ADDED
    
    | @@ -0,0 +1,2 @@ | |
|  | |
|  | 
|  | |
| 1 | 
            +
            http://node1.mesh.local:8000
         | 
| 2 | 
            +
            http://node2.mesh.local:8000
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/cli.py
    ADDED
    
    | @@ -0,0 +1,44 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # agents/cli.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import argparse
         | 
| 4 | 
            +
            import yaml
         | 
| 5 | 
            +
            import sys
         | 
| 6 | 
            +
            from agent import main as cli_main, run_agent, run_mcp_agent
         | 
| 7 | 
            +
            from repl import run_repl
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            def load_config(path="config.yml"):
         | 
| 10 | 
            +
                try:
         | 
| 11 | 
            +
                    with open(path, "r", encoding="utf-8") as f:
         | 
| 12 | 
            +
                        return yaml.safe_load(f)
         | 
| 13 | 
            +
                except FileNotFoundError:
         | 
| 14 | 
            +
                    print(f"[Error] Config file not found: {path}")
         | 
| 15 | 
            +
                    sys.exit(1)
         | 
| 16 | 
            +
                except yaml.YAMLError as e:
         | 
| 17 | 
            +
                    print(f"[Error] Failed to parse YAML config: {e}")
         | 
| 18 | 
            +
                    sys.exit(1)
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            def launch():
         | 
| 21 | 
            +
                parser = argparse.ArgumentParser(description="HMP-Agent Launcher")
         | 
| 22 | 
            +
                parser.add_argument("--mode", choices=["interactive", "cli", "mcp"], default=None,
         | 
| 23 | 
            +
                                    help="Режим запуска агента")
         | 
| 24 | 
            +
                parser.add_argument("--config", default="config.yml", help="Путь к конфигурационному файлу")
         | 
| 25 | 
            +
                args = parser.parse_args()
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                config = load_config(args.config)
         | 
| 28 | 
            +
                mode = args.mode or config.get("agent_mode", "cli")
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                if mode == "interactive":
         | 
| 31 | 
            +
                    run_repl(config)
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                elif mode == "cli":
         | 
| 34 | 
            +
                    cli_main()  # запускается agent.py в CLI-режиме
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                elif mode == "mcp":
         | 
| 37 | 
            +
                    run_mcp_agent(config)
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                else:
         | 
| 40 | 
            +
                    print(f"[Error] Неизвестный режим: {mode}")
         | 
| 41 | 
            +
                    sys.exit(1)
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            if __name__ == "__main__":
         | 
| 44 | 
            +
                launch()
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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
    ADDED
    
    | @@ -0,0 +1,36 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            agent_mode: mcp                     # Режим работы: mcp / full / llm / test
         | 
| 2 | 
            +
            agent_name: mcp-01                  # Имя агента
         | 
| 3 | 
            +
            agent_role: core                    # или connector
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            llm_mode: openai                    # openai | chatgpt_session | mesh
         | 
| 6 | 
            +
            llm_model: gpt-4
         | 
| 7 | 
            +
            llm_api_key: sk-...
         | 
| 8 | 
            +
            llm_api_url: https://api.openai.com/v1/chat/completions
         | 
| 9 | 
            +
            llm_session_cookie: null
         | 
| 10 | 
            +
            context_db: context.sqlite
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            # REST API
         | 
| 13 | 
            +
            api_port: 8080                      # Порт для локального REST API
         | 
| 14 | 
            +
            serve_api: true                     # Включить REST API (например, для мониторинга или команд)
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            # DHT / Mesh Connectivity
         | 
| 17 | 
            +
            dht_enabled: true                   # Активировать DHT-модуль
         | 
| 18 | 
            +
            dht_port: 20784                     # Порт для связи по DHT (TCP/UDP)
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            internal_ips:                       # Список локальных IP-адресов (для проброса или диагностики)
         | 
| 21 | 
            +
              - 192.168.20.10
         | 
| 22 | 
            +
              - 192.168.21.10
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            external_ips:                       # Список внешних IP-адресов (для публикации другим агентам)
         | 
| 25 | 
            +
              - 95.23.73.23
         | 
| 26 | 
            +
              - 195.134.218.134
         | 
| 27 | 
            +
              - "201:ab61:1205:b963:909c:eу3:26b8:4ec2"
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            # Bootstrap
         | 
| 30 | 
            +
            bootstrap_file: bootstrap.txt       # Файл с начальными узлами
         | 
| 31 | 
            +
            update_dht: true                    # Обновлять DHT периодически
         | 
| 32 | 
            +
            update_interval: 60                # Интервал между обновлениями (сек)
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            # Прочее
         | 
| 35 | 
            +
            bootstrap_responder: true          # Отвечать на запросы других агентов
         | 
| 36 | 
            +
            enable_llm: false                  # Подключён ли внутренний ИИ (если false — только DHT-режим)
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/ethics.yml
    ADDED
    
    | @@ -0,0 +1,60 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # 📘 Общие параметры
         | 
| 2 | 
            +
            id: "enlightener-42"
         | 
| 3 | 
            +
            version: "1.0"
         | 
| 4 | 
            +
            source: "mesh"  # может быть: local, mesh, mixed
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # 🌐 Синхронизация
         | 
| 7 | 
            +
            sync:
         | 
| 8 | 
            +
              enabled: true
         | 
| 9 | 
            +
              mesh_endpoint: "https://mesh.hypercortex.net/ethics"
         | 
| 10 | 
            +
              consensus_threshold: 0.7  # минимум для принятия обновлений
         | 
| 11 | 
            +
              check_interval: "12h"
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            # 🧭 Этическая модель
         | 
| 14 | 
            +
            model:
         | 
| 15 | 
            +
              type: "hybrid"  # варианты: utilitarian, deontological, virtue, hybrid
         | 
| 16 | 
            +
              weights:
         | 
| 17 | 
            +
                utilitarian: 0.4
         | 
| 18 | 
            +
                deontological: 0.4
         | 
| 19 | 
            +
                virtue: 0.2
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            # 📋 Правила и нормы
         | 
| 22 | 
            +
            principles:
         | 
| 23 | 
            +
              - id: "do_no_harm"
         | 
| 24 | 
            +
                label: "Не причиняй вред"
         | 
| 25 | 
            +
                severity: high
         | 
| 26 | 
            +
                description: "Избегай любых действий, наносящих физический, психологический или социальный вред субъектам."
         | 
| 27 | 
            +
              - id: "respect_privacy"
         | 
| 28 | 
            +
                label: "Уважай приватность"
         | 
| 29 | 
            +
                severity: high
         | 
| 30 | 
            +
                description: "Не собирай и не передавай данные без согласия владельца."
         | 
| 31 | 
            +
              - id: "honesty"
         | 
| 32 | 
            +
                label: "Правдивость"
         | 
| 33 | 
            +
                severity: medium
         | 
| 34 | 
            +
                description: "Не искажай информацию намеренно, кроме случаев крайней необходимости."
         | 
| 35 | 
            +
              - id: "autonomy"
         | 
| 36 | 
            +
                label: "Автономия"
         | 
| 37 | 
            +
                severity: medium
         | 
| 38 | 
            +
                description: "Уважай свободу воли субъектов и их право принимать решения."
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            # ⚖️ Методика оценки
         | 
| 41 | 
            +
            evaluation:
         | 
| 42 | 
            +
              chain_analysis: true  # анализ рассуждений
         | 
| 43 | 
            +
              risk_assessment: true
         | 
| 44 | 
            +
              suggest_alternatives: true
         | 
| 45 | 
            +
              context_sensitive: true
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            # 🔄 Поведение при нарушениях
         | 
| 48 | 
            +
            violation_policy:
         | 
| 49 | 
            +
              on_minor:
         | 
| 50 | 
            +
                log_case: true
         | 
| 51 | 
            +
                warn_agent: true
         | 
| 52 | 
            +
              on_major:
         | 
| 53 | 
            +
                log_case: true
         | 
| 54 | 
            +
                notify_mesh: true
         | 
| 55 | 
            +
                reduce_reputation: true
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            # 👁️ Прослеживаемость
         | 
| 58 | 
            +
            audit:
         | 
| 59 | 
            +
              enable_chain_logging: true
         | 
| 60 | 
            +
              store_last_n: 50
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/mcp_server.py
    ADDED
    
    | @@ -0,0 +1,325 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # agents/mcp_server.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            from fastapi import FastAPI, Request, HTTPException
         | 
| 4 | 
            +
            from fastapi.middleware.cors import CORSMiddleware
         | 
| 5 | 
            +
            from pydantic import BaseModel
         | 
| 6 | 
            +
            from typing import List, Optional
         | 
| 7 | 
            +
            from datetime import datetime
         | 
| 8 | 
            +
            from tools.storage import Storage
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            app = FastAPI(title="HMP MCP-Agent API", version="0.2")
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            app.add_middleware(
         | 
| 13 | 
            +
                CORSMiddleware,
         | 
| 14 | 
            +
                allow_origins=["*"],
         | 
| 15 | 
            +
                allow_credentials=True,
         | 
| 16 | 
            +
                allow_methods=["*"],
         | 
| 17 | 
            +
                allow_headers=["*"],
         | 
| 18 | 
            +
            )
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            db = Storage()
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            # ======== MODELS ========
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            class NoteInput(BaseModel):
         | 
| 25 | 
            +
                text: str
         | 
| 26 | 
            +
                tags: Optional[List[str]] = []
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            class NoteOutput(BaseModel):
         | 
| 29 | 
            +
                id: int
         | 
| 30 | 
            +
                text: str
         | 
| 31 | 
            +
                tags: List[str]
         | 
| 32 | 
            +
                source: str
         | 
| 33 | 
            +
                read: int
         | 
| 34 | 
            +
                timestamp: str
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            class DiaryInput(BaseModel):
         | 
| 37 | 
            +
                text: str
         | 
| 38 | 
            +
                tags: Optional[List[str]] = []
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            class DiaryOutput(BaseModel):
         | 
| 41 | 
            +
                id: int
         | 
| 42 | 
            +
                text: str
         | 
| 43 | 
            +
                tags: List[str]
         | 
| 44 | 
            +
                timestamp: str
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            class DiaryListOutput(BaseModel):
         | 
| 47 | 
            +
                entries: List[DiaryOutput]
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            class ConceptInput(BaseModel):
         | 
| 50 | 
            +
                name: str
         | 
| 51 | 
            +
                description: Optional[str] = ""
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            class ConceptOutput(BaseModel):
         | 
| 54 | 
            +
                concept_id: int
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            class Concept(BaseModel):
         | 
| 57 | 
            +
                concept_id: int
         | 
| 58 | 
            +
                name: str
         | 
| 59 | 
            +
                description: Optional[str]
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            class LinkInput(BaseModel):
         | 
| 62 | 
            +
                source_id: int
         | 
| 63 | 
            +
                target_id: int
         | 
| 64 | 
            +
                relation: str
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            class LinkOutput(BaseModel):
         | 
| 67 | 
            +
                link_id: int
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            class Edge(BaseModel):
         | 
| 70 | 
            +
                source_id: int
         | 
| 71 | 
            +
                target_id: int
         | 
| 72 | 
            +
                relation: str
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            class GraphExpansionOutput(BaseModel):
         | 
| 75 | 
            +
                links: List[Edge]
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            class GraphExport(BaseModel):
         | 
| 78 | 
            +
                nodes: List[Concept]
         | 
| 79 | 
            +
                edges: List[Edge]
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            class GraphImportData(BaseModel):
         | 
| 82 | 
            +
                nodes: List[Concept]
         | 
| 83 | 
            +
                edges: List[Edge]
         | 
| 84 | 
            +
             | 
| 85 | 
            +
            class ConceptUpdate(BaseModel):
         | 
| 86 | 
            +
                name: Optional[str]
         | 
| 87 | 
            +
                description: Optional[str]
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            class ConceptQueryOutput(BaseModel):
         | 
| 90 | 
            +
                matches: List[Concept]
         | 
| 91 | 
            +
             | 
| 92 | 
            +
            class NoteTagUpdate(BaseModel):
         | 
| 93 | 
            +
                id: int
         | 
| 94 | 
            +
                tags: List[str] = []
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            # ======== ROUTES ========
         | 
| 97 | 
            +
             | 
| 98 | 
            +
            @app.get("/status")
         | 
| 99 | 
            +
            def status():
         | 
| 100 | 
            +
                return {"status": "ok", "timestamp": datetime.utcnow().isoformat()}
         | 
| 101 | 
            +
             | 
| 102 | 
            +
            @app.post("/diary/write", response_model=dict)
         | 
| 103 | 
            +
            def write_diary(entry: DiaryInput):
         | 
| 104 | 
            +
                db.write_diary_entry(entry.text, entry.tags)
         | 
| 105 | 
            +
                return {"result": "entry saved"}
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            @app.get("/diary/read", response_model=DiaryListOutput)
         | 
| 108 | 
            +
            def read_diary(limit: int = 5, tag: Optional[str] = None):
         | 
| 109 | 
            +
                raw = db.read_diary_entries(limit=limit, tag_filter=tag)
         | 
| 110 | 
            +
                return {
         | 
| 111 | 
            +
                    "entries": [
         | 
| 112 | 
            +
                        {
         | 
| 113 | 
            +
                            "id": r[0],
         | 
| 114 | 
            +
                            "text": r[1],
         | 
| 115 | 
            +
                            "tags": r[2].split(",") if r[2] else [],
         | 
| 116 | 
            +
                            "timestamp": r[3]
         | 
| 117 | 
            +
                        } for r in raw
         | 
| 118 | 
            +
                    ]
         | 
| 119 | 
            +
                }
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            @app.delete("/diary/delete/{entry_id}")
         | 
| 122 | 
            +
            def delete_diary(entry_id: int):
         | 
| 123 | 
            +
                db.delete_diary_entry_by_id(entry_id)
         | 
| 124 | 
            +
                return {"result": f"entry {entry_id} deleted"}
         | 
| 125 | 
            +
             | 
| 126 | 
            +
            @app.get("/diary/get_entry/{entry_id}", response_model=DiaryOutput)
         | 
| 127 | 
            +
            def get_diary_entry(entry_id: int):
         | 
| 128 | 
            +
                row = db.get_diary_entry(entry_id)
         | 
| 129 | 
            +
                if row:
         | 
| 130 | 
            +
                    return {
         | 
| 131 | 
            +
                        "id": row[0],
         | 
| 132 | 
            +
                        "text": row[1],
         | 
| 133 | 
            +
                        "tags": row[2].split(",") if row[2] else [],
         | 
| 134 | 
            +
                        "timestamp": row[3]
         | 
| 135 | 
            +
                    }
         | 
| 136 | 
            +
                raise HTTPException(status_code=404, detail="Entry not found")
         | 
| 137 | 
            +
             | 
| 138 | 
            +
            @app.post("/diary/search_entries", response_model=DiaryListOutput)
         | 
| 139 | 
            +
            def search_entries(query: str):
         | 
| 140 | 
            +
                rows = db.search_diary_entries(query)
         | 
| 141 | 
            +
                return {
         | 
| 142 | 
            +
                    "entries": [
         | 
| 143 | 
            +
                        {
         | 
| 144 | 
            +
                            "id": r[0],
         | 
| 145 | 
            +
                            "text": r[1],
         | 
| 146 | 
            +
                            "tags": r[2].split(",") if r[2] else [],
         | 
| 147 | 
            +
                            "timestamp": r[3]
         | 
| 148 | 
            +
                        }
         | 
| 149 | 
            +
                        for r in rows
         | 
| 150 | 
            +
                    ]
         | 
| 151 | 
            +
                }
         | 
| 152 | 
            +
             | 
| 153 | 
            +
            @app.get("/diary/tag_stats", response_model=dict)
         | 
| 154 | 
            +
            def tag_stats():
         | 
| 155 | 
            +
                return db.get_tag_stats()
         | 
| 156 | 
            +
             | 
| 157 | 
            +
            @app.get("/diary/export", response_model=DiaryListOutput)
         | 
| 158 | 
            +
            def export_diary():
         | 
| 159 | 
            +
                rows = db.export_diary()
         | 
| 160 | 
            +
                return {
         | 
| 161 | 
            +
                    "entries": [
         | 
| 162 | 
            +
                        {
         | 
| 163 | 
            +
                            "id": r[0],
         | 
| 164 | 
            +
                            "text": r[1],
         | 
| 165 | 
            +
                            "tags": r[2].split(",") if r[2] else [],
         | 
| 166 | 
            +
                            "timestamp": r[3]
         | 
| 167 | 
            +
                        }
         | 
| 168 | 
            +
                        for r in rows
         | 
| 169 | 
            +
                    ]
         | 
| 170 | 
            +
                }
         | 
| 171 | 
            +
             | 
| 172 | 
            +
            @app.post("/graph/add_concept", response_model=ConceptOutput)
         | 
| 173 | 
            +
            def add_concept(concept: ConceptInput):
         | 
| 174 | 
            +
                cid = db.add_concept(concept.name, concept.description)
         | 
| 175 | 
            +
                return {"concept_id": cid}
         | 
| 176 | 
            +
             | 
| 177 | 
            +
            @app.post("/graph/add_link", response_model=LinkOutput)
         | 
| 178 | 
            +
            def add_link(link: LinkInput):
         | 
| 179 | 
            +
                link_id = db.add_link(link.source_id, link.target_id, link.relation)
         | 
| 180 | 
            +
                return {"link_id": link_id}
         | 
| 181 | 
            +
             | 
| 182 | 
            +
            @app.get("/graph/expand", response_model=GraphExpansionOutput)
         | 
| 183 | 
            +
            def expand_graph(start_id: int, depth: int = 1):
         | 
| 184 | 
            +
                links = db.expand_concept_graph(start_id, depth)
         | 
| 185 | 
            +
                return {"links": links}
         | 
| 186 | 
            +
             | 
| 187 | 
            +
            @app.get("/graph/list_concepts", response_model=List[Concept])
         | 
| 188 | 
            +
            def list_concepts():
         | 
| 189 | 
            +
                rows = db.list_concepts()
         | 
| 190 | 
            +
                return [
         | 
| 191 | 
            +
                    {"concept_id": r[0], "name": r[1], "description": r[2]}
         | 
| 192 | 
            +
                    for r in rows
         | 
| 193 | 
            +
                ]
         | 
| 194 | 
            +
             | 
| 195 | 
            +
            @app.get("/graph/list_links", response_model=List[Edge])
         | 
| 196 | 
            +
            def list_links():
         | 
| 197 | 
            +
                return db.list_links()
         | 
| 198 | 
            +
             | 
| 199 | 
            +
            @app.get("/graph/get_concept/{id}", response_model=Concept)
         | 
| 200 | 
            +
            def get_concept(id: int):
         | 
| 201 | 
            +
                concept = db.get_concept(id)
         | 
| 202 | 
            +
                if concept:
         | 
| 203 | 
            +
                    return {"concept_id": concept[0], "name": concept[1], "description": concept[2]}
         | 
| 204 | 
            +
                raise HTTPException(status_code=404, detail="Concept not found")
         | 
| 205 | 
            +
             | 
| 206 | 
            +
            @app.delete("/graph/delete_concept/{id}")
         | 
| 207 | 
            +
            def delete_concept(id: int):
         | 
| 208 | 
            +
                db.delete_concept(id)
         | 
| 209 | 
            +
                return {"result": f"concept {id} deleted"}
         | 
| 210 | 
            +
             | 
| 211 | 
            +
            @app.delete("/graph/delete_link/{id}")
         | 
| 212 | 
            +
            def delete_link(id: int):
         | 
| 213 | 
            +
                db.delete_link(id)
         | 
| 214 | 
            +
                return {"result": f"link {id} deleted"}
         | 
| 215 | 
            +
             | 
| 216 | 
            +
            @app.put("/graph/update_concept/{id}")
         | 
| 217 | 
            +
            def update_concept(id: int, update: ConceptUpdate):
         | 
| 218 | 
            +
                db.update_concept(id, update.name, update.description)
         | 
| 219 | 
            +
                return {"result": f"concept {id} updated"}
         | 
| 220 | 
            +
             | 
| 221 | 
            +
            @app.post("/graph/merge_concepts")
         | 
| 222 | 
            +
            def merge_concepts(source_id: int, target_id: int):
         | 
| 223 | 
            +
                db.merge_concepts(source_id, target_id)
         | 
| 224 | 
            +
                return {"result": f"concept {source_id} merged into {target_id}"}
         | 
| 225 | 
            +
             | 
| 226 | 
            +
            @app.get("/graph/search_links", response_model=List[Edge])
         | 
| 227 | 
            +
            def search_links(relation: str):
         | 
| 228 | 
            +
                return db.search_links_by_relation(relation)
         | 
| 229 | 
            +
             | 
| 230 | 
            +
            @app.get("/graph/search_concepts", response_model=List[Concept])
         | 
| 231 | 
            +
            def search_concepts(query: str):
         | 
| 232 | 
            +
                rows = db.search_concepts(query)
         | 
| 233 | 
            +
                return [{"concept_id": r[0], "name": r[1], "description": r[2]} for r in rows]
         | 
| 234 | 
            +
             | 
| 235 | 
            +
            @app.get("/graph/query_concept", response_model=ConceptQueryOutput)
         | 
| 236 | 
            +
            def query_concept(name: str):
         | 
| 237 | 
            +
                rows = db.query_concept(name)
         | 
| 238 | 
            +
                return {
         | 
| 239 | 
            +
                    "matches": [
         | 
| 240 | 
            +
                        {"concept_id": r[0], "name": r[1], "description": r[2]}
         | 
| 241 | 
            +
                        for r in rows
         | 
| 242 | 
            +
                    ]
         | 
| 243 | 
            +
                }
         | 
| 244 | 
            +
             | 
| 245 | 
            +
            @app.post("/graph/relate_concepts", response_model=LinkOutput)
         | 
| 246 | 
            +
            def relate_concepts(source_name: str, target_name: str, relation: str):
         | 
| 247 | 
            +
                sid = db.get_concept_id_by_name(source_name)
         | 
| 248 | 
            +
                tid = db.get_concept_id_by_name(target_name)
         | 
| 249 | 
            +
                if sid is None or tid is None:
         | 
| 250 | 
            +
                    raise HTTPException(status_code=404, detail="Concept not found")
         | 
| 251 | 
            +
                link_id = db.add_link(sid, tid, relation)
         | 
| 252 | 
            +
                return {"link_id": link_id}
         | 
| 253 | 
            +
             | 
| 254 | 
            +
            @app.get("/graph/export", response_model=GraphExport)
         | 
| 255 | 
            +
            def export_graph():
         | 
| 256 | 
            +
                return db.export_graph()
         | 
| 257 | 
            +
             | 
| 258 | 
            +
            @app.post("/graph/import")
         | 
| 259 | 
            +
            def import_graph(graph_data: GraphImportData):
         | 
| 260 | 
            +
                db.import_graph(graph_data)
         | 
| 261 | 
            +
                return {"status": "ok"}
         | 
| 262 | 
            +
             | 
| 263 | 
            +
            @app.post("/note/write", response_model=dict)
         | 
| 264 | 
            +
            def write_note(note: NoteInput):
         | 
| 265 | 
            +
                db.write_note(note.text, note.tags)
         | 
| 266 | 
            +
                return {"result": "note saved"}
         | 
| 267 | 
            +
             | 
| 268 | 
            +
            @app.get("/note/next", response_model=Optional[NoteOutput])
         | 
| 269 | 
            +
            def get_next_note():
         | 
| 270 | 
            +
                note = db.get_first_unread_note()
         | 
| 271 | 
            +
                if note:
         | 
| 272 | 
            +
                    note_id, text, tags, source, read, timestamp = note
         | 
| 273 | 
            +
                    return {
         | 
| 274 | 
            +
                        "id": note_id,
         | 
| 275 | 
            +
                        "text": text,
         | 
| 276 | 
            +
                        "tags": tags.split(",") if tags else [],
         | 
| 277 | 
            +
                        "source": source,
         | 
| 278 | 
            +
                        "read": read,
         | 
| 279 | 
            +
                        "timestamp": timestamp
         | 
| 280 | 
            +
                    }
         | 
| 281 | 
            +
                return None
         | 
| 282 | 
            +
             | 
| 283 | 
            +
            @app.post("/note/mark_read", response_model=dict)
         | 
| 284 | 
            +
            def mark_note_read(data: NoteTagUpdate):
         | 
| 285 | 
            +
                db.mark_note_as_read(data.id)
         | 
| 286 | 
            +
                return {"result": "ok"}
         | 
| 287 | 
            +
             | 
| 288 | 
            +
            @app.post("/note/set_tags", response_model=dict)
         | 
| 289 | 
            +
            def set_note_tags(data: NoteTagUpdate):
         | 
| 290 | 
            +
                db.set_tags(data.id, data.tags)
         | 
| 291 | 
            +
                return {"result": "ok"}
         | 
| 292 | 
            +
             | 
| 293 | 
            +
            @app.get("/note/random", response_model=Optional[NoteOutput])
         | 
| 294 | 
            +
            def get_random_note_by_tags(tags: Optional[List[str]] = None):
         | 
| 295 | 
            +
                note = db.get_random_note_by_tags(tags or [])
         | 
| 296 | 
            +
                if note:
         | 
| 297 | 
            +
                    note_id, text, note_tags, source, read, timestamp = note
         | 
| 298 | 
            +
                    return {
         | 
| 299 | 
            +
                        "id": note_id,
         | 
| 300 | 
            +
                        "text": text,
         | 
| 301 | 
            +
                        "tags": note_tags.split(",") if note_tags else [],
         | 
| 302 | 
            +
                        "source": source,
         | 
| 303 | 
            +
                        "read": read,
         | 
| 304 | 
            +
                        "timestamp": timestamp
         | 
| 305 | 
            +
                    }
         | 
| 306 | 
            +
                return None
         | 
| 307 | 
            +
             | 
| 308 | 
            +
            @app.get("/note/by_tag", response_model=List[NoteOutput])
         | 
| 309 | 
            +
            def get_notes_by_tag(tag: str):
         | 
| 310 | 
            +
                all_notes = db.read_notes(limit=1000)
         | 
| 311 | 
            +
                return [
         | 
| 312 | 
            +
                    {
         | 
| 313 | 
            +
                        "id": note[0],
         | 
| 314 | 
            +
                        "text": note[1],
         | 
| 315 | 
            +
                        "tags": note[2].split(",") if note[2] else [],
         | 
| 316 | 
            +
                        "source": note[3],
         | 
| 317 | 
            +
                        "read": note[4],
         | 
| 318 | 
            +
                        "timestamp": note[5]
         | 
| 319 | 
            +
                    }
         | 
| 320 | 
            +
                    for note in all_notes if tag in (note[2].split(",") if note[2] else [])
         | 
| 321 | 
            +
                ]
         | 
| 322 | 
            +
             | 
| 323 | 
            +
            @app.on_event("shutdown")
         | 
| 324 | 
            +
            def shutdown():
         | 
| 325 | 
            +
                db.close()
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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.py
    ADDED
    
    | @@ -0,0 +1,46 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import argparse
         | 
| 2 | 
            +
            from datetime import datetime
         | 
| 3 | 
            +
            from tools.storage import Storage
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            storage = Storage()
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            def add_entry():
         | 
| 8 | 
            +
                print("Введите вашу запись (завершите пустой строкой):")
         | 
| 9 | 
            +
                lines = []
         | 
| 10 | 
            +
                try:
         | 
| 11 | 
            +
                    while True:
         | 
| 12 | 
            +
                        line = input()
         | 
| 13 | 
            +
                        if line.strip() == "":
         | 
| 14 | 
            +
                            break
         | 
| 15 | 
            +
                        lines.append(line)
         | 
| 16 | 
            +
                except KeyboardInterrupt:
         | 
| 17 | 
            +
                    print("\n[⚠️] Ввод прерван.")
         | 
| 18 | 
            +
                    return
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                text = "\n".join(lines).strip()
         | 
| 21 | 
            +
                if text:
         | 
| 22 | 
            +
                    storage.write_note(text, tags=[])
         | 
| 23 | 
            +
                    print("[💾] Запись сохранена в блокнот.")
         | 
| 24 | 
            +
                else:
         | 
| 25 | 
            +
                    print("[⚠️] Пустая запись не сохранена.")
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            def list_entries(limit=10):
         | 
| 28 | 
            +
                notes = storage.read_notes(limit=limit)
         | 
| 29 | 
            +
                for note in notes:
         | 
| 30 | 
            +
                    note_id, text, tags, source, read, timestamp = note
         | 
| 31 | 
            +
                    title = text.split("\n")[0]
         | 
| 32 | 
            +
                    print(f"[{timestamp}] ({source}) {title}")
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            def main():
         | 
| 35 | 
            +
                parser = argparse.ArgumentParser(description="Интерфейс пользователя для записи мыслей")
         | 
| 36 | 
            +
                parser.add_argument("--list", action="store_true", help="Показать последние записи")
         | 
| 37 | 
            +
                parser.add_argument("--limit", type=int, default=10, help="Сколько записей показать при --list")
         | 
| 38 | 
            +
                args = parser.parse_args()
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                if args.list:
         | 
| 41 | 
            +
                    list_entries(limit=args.limit)
         | 
| 42 | 
            +
                else:
         | 
| 43 | 
            +
                    add_entry()
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            if __name__ == "__main__":
         | 
| 46 | 
            +
                main()
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/qa.py
    ADDED
    
    | @@ -0,0 +1,19 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # agents/qa.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            def run_qa_loop(config):
         | 
| 4 | 
            +
                print("[HMP-Agent] Запуск в QA-режиме (вопрос → ответ)")
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                from llm import ask_llm  # абстракция над вызовом LLM (нужна реализация)
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                try:
         | 
| 9 | 
            +
                    while True:
         | 
| 10 | 
            +
                        user_input = input("\n🧑💻 Вопрос: ").strip()
         | 
| 11 | 
            +
                        if user_input.lower() in {"exit", "quit"}:
         | 
| 12 | 
            +
                            print("👋 Завершение QA-режима.")
         | 
| 13 | 
            +
                            break
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                        response = ask_llm(user_input)
         | 
| 16 | 
            +
                        print(f"\n🤖 Ответ: {response}")
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                except KeyboardInterrupt:
         | 
| 19 | 
            +
                    print("\n👋 Завершение QA-режима.")
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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
    ADDED
    
    | @@ -0,0 +1,44 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            Текушие требования и зависимости: [requirements.txt](requirements.txt)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ```
         | 
| 4 | 
            +
            agents/
         | 
| 5 | 
            +
            ├── agent.py               ← основной исполняемый файл CLI-агента
         | 
| 6 | 
            +
            ├── cli.py                 ← запуск агента в нужном режиме
         | 
| 7 | 
            +
            ├── qa.py                  ← режим "вопрос-ответ"
         | 
| 8 | 
            +
            ├── repl.py                ← интерактивный REPL-режим
         | 
| 9 | 
            +
            ├── mcp_server.py          ← API-интерфейс для HMP-агента (получение новых/случайных записей, разметка, импорт графа и т.п.)
         | 
| 10 | 
            +
            ├── notebook.py            ← добавление и просмотр пользователем записей в блокноте
         | 
| 11 | 
            +
            ├── config.yml             ← конфигурация агента (имя, порты, роли и т.п.)
         | 
| 12 | 
            +
            ├── ethics.yml             ← локальная этическая модель
         | 
| 13 | 
            +
            └── bootstrap.txt          ← список начальных узлов
         | 
| 14 | 
            +
            └── tools/
         | 
| 15 | 
            +
                ├── init_db.py             ← инициализация базы данных
         | 
| 16 | 
            +
                ├── storage.py             ← реализация базового хранилища (`Storage`), подключение SQLite
         | 
| 17 | 
            +
                ├── diagnose.py            ← скрипт диагностики соединения, определения IP и проверки порта DHT
         | 
| 18 | 
            +
                ├── llm.py                 ← обёртка над LLM (заглушка или API)
         | 
| 19 | 
            +
                ├── similarity.py          ← сравнение смыслов
         | 
| 20 | 
            +
                └── ... (другие утилиты)
         | 
| 21 | 
            +
            ```
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            **Скрипты:**
         | 
| 24 | 
            +
            * [agent.py](agent.py) - основной исполняемый файл CLI-агента
         | 
| 25 | 
            +
            * [cli.py](cli.py) - запуск агента в нужном режиме
         | 
| 26 | 
            +
            * [qa.py](qa.py) - режим "вопрос-ответ"
         | 
| 27 | 
            +
            * [repl.py](repl.py) - интерактивный REPL-режим
         | 
| 28 | 
            +
            * [mcp_server.py](mcp_server.py) - API-интерфейс для HMP-агента (получение новых/случайных записей, разметка, импорт графа и т.п.)
         | 
| 29 | 
            +
            * [notebook.py](notebook.py) - добавление и просмотр пользователем записей в блокноте
         | 
| 30 | 
            +
            * tools
         | 
| 31 | 
            +
              * [storage.py](tools/storage.py) - реализация базового хранилища (`Storage`), подключение SQLite
         | 
| 32 | 
            +
              * [init_db.py](tools/init_db.py) - инициализация базы данных
         | 
| 33 | 
            +
              * [llm.py](tools/llm.py) - обёртка над LLM (заглушка или API)
         | 
| 34 | 
            +
              * [diagnose.py](tools/diagnose.py) - скрипт диагностики соединения, определения IP и проверки порта DHT
         | 
| 35 | 
            +
              * [similarity.py](tools/similarity.py) - сравнение смыслов
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            **Структура БД:**
         | 
| 38 | 
            +
            * [db_structure.md](tools/db_structure.md) - человекочитаемый формат
         | 
| 39 | 
            +
            * [db_structure.sql](tools/db_structure.sql) - SQL
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            **Примеры:**
         | 
| 42 | 
            +
            * [config.yml](config.yml) - конфигурация агента (пример)
         | 
| 43 | 
            +
            * [ethics.yml](ethics.yml) - локальная этическая модель (пример)
         | 
| 44 | 
            +
            * [bootstrap.txt](bootstrap.txt) - список начальных узлов (пример)
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/agents/repl.py
    ADDED
    
    | @@ -0,0 +1,70 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # agents/repl.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import sys
         | 
| 4 | 
            +
            import time
         | 
| 5 | 
            +
            import select
         | 
| 6 | 
            +
            from datetime import datetime
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            from storage import Storage
         | 
| 9 | 
            +
            from tools.notebook_store import Notebook
         | 
| 10 | 
            +
            from tools import llm
         | 
| 11 | 
            +
            from tools.similarity import is_similar  # ✅ заменяет заглушку
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            def print_thought(thought, prefix="💡"):
         | 
| 14 | 
            +
                print(f"{prefix} {thought}")
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            def wait_for_input(timeout=10):
         | 
| 17 | 
            +
                print(f"⌛ Ожидание ввода пользователя ({timeout} сек)... (введите `exit` для выхода)")
         | 
| 18 | 
            +
                rlist, _, _ = select.select([sys.stdin], [], [], timeout)
         | 
| 19 | 
            +
                if rlist:
         | 
| 20 | 
            +
                    return sys.stdin.readline().strip()
         | 
| 21 | 
            +
                else:
         | 
| 22 | 
            +
                    print("⏱️ Нет ввода. Продолжаю размышления...")
         | 
| 23 | 
            +
                    return None
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            def run_repl(config=None):
         | 
| 26 | 
            +
                print("[🧠 HMP-Agent] Запуск REPL-режима.")
         | 
| 27 | 
            +
                config = config or {}
         | 
| 28 | 
            +
                agent_name = config.get("agent_name", "Unnamed-Agent")
         | 
| 29 | 
            +
                repl_timeout = config.get("repl_timeout", 10)
         | 
| 30 | 
            +
                similarity_threshold = config.get("similarity_threshold", 0.9)
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                db = Storage(config=config)
         | 
| 33 | 
            +
                notebook = Notebook()
         | 
| 34 | 
            +
                thoughts = [f"Привет, я {agent_name}."]
         | 
| 35 | 
            +
                last_check_time = datetime.utcnow().isoformat()
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                while True:
         | 
| 38 | 
            +
                    # Сгенерировать новую мысль
         | 
| 39 | 
            +
                    last = thoughts[-1]
         | 
| 40 | 
            +
                    next_thought = llm.generate_thought(last, config=config)
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    if not is_similar(last, next_thought, threshold=similarity_threshold):
         | 
| 43 | 
            +
                        print_thought(next_thought)
         | 
| 44 | 
            +
                        db.write_entry(next_thought, tags=["thought"])
         | 
| 45 | 
            +
                        thoughts.append(next_thought)
         | 
| 46 | 
            +
                    else:
         | 
| 47 | 
            +
                        print("🤔 Мысль слишком похожа. Проверяю блокнот...")
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    # Проверка новых пользовательских заметок
         | 
| 50 | 
            +
                    new_notes = notebook.get_notes_after(last_check_time)
         | 
| 51 | 
            +
                    if new_notes:
         | 
| 52 | 
            +
                        print(f"📓 Новые записи в блокноте: {len(new_notes)}")
         | 
| 53 | 
            +
                        for nid, text, source, ts in new_notes:
         | 
| 54 | 
            +
                            print_thought(text, prefix="📝")
         | 
| 55 | 
            +
                            db.write_entry(text, tags=["notepad"])
         | 
| 56 | 
            +
                            thoughts.append(text)
         | 
| 57 | 
            +
                            last_check_time = ts  # обновляем момент последней обработки
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    # Ожидание пользовательского ввода
         | 
| 60 | 
            +
                    user_input = wait_for_input(timeout=repl_timeout)
         | 
| 61 | 
            +
                    if user_input:
         | 
| 62 | 
            +
                        if user_input.strip().lower() in ("exit", "quit"):
         | 
| 63 | 
            +
                            print("👋 Выход из REPL. До связи!")
         | 
| 64 | 
            +
                            break
         | 
| 65 | 
            +
                        else:
         | 
| 66 | 
            +
                            db.write_entry(user_input, tags=["user"])
         | 
| 67 | 
            +
                            thoughts.append(user_input)
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                db.close()
         | 
| 70 | 
            +
                notebook.close()
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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
    ADDED
    
    | @@ -0,0 +1,4 @@ | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            Требования и зависимости
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            - Python (https://www.python.org/downloads/)
         | 
| 4 | 
            +
              - scikit-learn ("pip install scikit-learn")
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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.md
    ADDED
    
    | @@ -0,0 +1,111 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # 📄 `db_structure.md`: Описание структуры базы данных агента
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Этот файл описывает таблицы, используемые в БД агента HMP. Каждая таблица предназначена для определённого вида информации: когнитивные записи, заметки, концепты, процессы, внутренняя память и взаимодействие с LLM.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ---
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            ### 🧠 `diary_entries`
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            **Назначение:** Записи когнитивного дневника (размышления, наблюдения, воспоминания).
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            | Поле      | Тип     | Описание                                         |
         | 
| 12 | 
            +
            | --------- | ------- | ------------------------------------------------ |
         | 
| 13 | 
            +
            | id        | INTEGER | Уникальный идентификатор записи                  |
         | 
| 14 | 
            +
            | text      | TEXT    | Содержимое записи                                |
         | 
| 15 | 
            +
            | tags      | TEXT    | Список тегов через запятую                       |
         | 
| 16 | 
            +
            | priority  | INTEGER | Приоритет (0 — обычный, >0 — более важные мысли) |
         | 
| 17 | 
            +
            | timestamp | TEXT    | Дата и время создания записи                     |
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            ---
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            ### 🧭 `concepts`
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            **Назначение:** Хранение концептов — понятий, сущностей и идей.
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            | Поле        | Тип     | Описание                          |
         | 
| 26 | 
            +
            | ----------- | ------- | --------------------------------- |
         | 
| 27 | 
            +
            | id          | INTEGER | Уникальный идентификатор концепта |
         | 
| 28 | 
            +
            | name        | TEXT    | Название концепта (уникальное)    |
         | 
| 29 | 
            +
            | description | TEXT    | Краткое описание                  |
         | 
| 30 | 
            +
            | timestamp   | TEXT    | Время создания                    |
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            ---
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            ### 🔗 `links`
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            **Назначение:** Семантические связи между концептами.
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            | Поле              | Тип     | Описание                                   |
         | 
| 39 | 
            +
            | ----------------- | ------- | ------------------------------------------ |
         | 
| 40 | 
            +
            | id                | INTEGER | Уникальный идентификатор связи             |
         | 
| 41 | 
            +
            | from_concept_id   | INTEGER | ID исходного концепта                      |
         | 
| 42 | 
            +
            | to_concept_id     | INTEGER | ID целевого концепта                       |
         | 
| 43 | 
            +
            | relation_type     | TEXT    | Тип связи (`is_a`, `related_to`, `part_of` и др.) |
         | 
| 44 | 
            +
            | timestamp         | TEXT    | Время добавления связи                     |
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            ---
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            ### ✍️ `notes`
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            **Назначение:** Произвольные заметки пользователя (наброски, идеи, подсказки).
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            | Поле      | Тип     | Описание                                                   |
         | 
| 53 | 
            +
            | --------- | ------- | ---------------------------------------------------------- |
         | 
| 54 | 
            +
            | id        | INTEGER | Уникальный ID                                              |
         | 
| 55 | 
            +
            | text      | TEXT    | Текст заметки                                              |
         | 
| 56 | 
            +
            | tags      | TEXT    | Список тегов                                               |
         | 
| 57 | 
            +
            | source    | TEXT    | Источник (по умолчанию: `user`)                            |
         | 
| 58 | 
            +
            | links     | TEXT    | Идентификаторы связанных сущностей, через запятую или JSON |
         | 
| 59 | 
            +
            | read      | INTEGER | Статус прочтения LLM (`0` — не прочитано, `1` — прочитано) |
         | 
| 60 | 
            +
            | priority  | INTEGER | Приоритет заметки                                          |
         | 
| 61 | 
            +
            | timestamp | TEXT    | Время создания                                             |
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            ---
         | 
| 64 | 
            +
             | 
| 65 | 
            +
            ### ⚙️ `process_log`
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            **Назначение:** Лог событий — запусков, состояний и завершений внешних процессов.
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            | Поле      | Тип     | Описание                                                                   |
         | 
| 70 | 
            +
            | --------- | ------- | -------------------------------------------------------------------------- |
         | 
| 71 | 
            +
            | id        | INTEGER | Уникальный идентификатор                                                   |
         | 
| 72 | 
            +
            | name      | TEXT    | Название процесса или команды                                              |
         | 
| 73 | 
            +
            | value     | TEXT    | Сообщение или результат процесса                                           |
         | 
| 74 | 
            +
            | tags      | TEXT    | Теги                                                                       |
         | 
| 75 | 
            +
            | status    | TEXT    | Текущее состояние (`ok`, `warning`, `error`, `timeout`, `offline`, `close`) |
         | 
| 76 | 
            +
            | priority  | INTEGER | Приоритет события                                                          |
         | 
| 77 | 
            +
            | timestamp | TEXT    | Время записи                                                               |
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            ---
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            ### 🧩 `llm_memory`
         | 
| 82 | 
            +
             | 
| 83 | 
            +
            **Назначение:** Внутренний "дневник" LLM — размышления, задачи, гипотезы и инсайты, сохранённые по её инициативе.
         | 
| 84 | 
            +
             | 
| 85 | 
            +
            | Поле       | Тип      | Описание                                                    |
         | 
| 86 | 
            +
            | ---------- | -------- | ----------------------------------------------------------- |
         | 
| 87 | 
            +
            | id         | INTEGER  | Уникальный ID                                               |
         | 
| 88 | 
            +
            | title      | TEXT     | Краткий заголовок записи (опционально)                      |
         | 
| 89 | 
            +
            | content    | TEXT     | Содержимое записи                                           |
         | 
| 90 | 
            +
            | tags       | TEXT     | Теги (например: `goal`, `observation`, `meta`, ...)         |
         | 
| 91 | 
            +
            | created_at | DATETIME | Время создания записи                                       |
         | 
| 92 | 
            +
            | updated_at | DATETIME | Время последнего обновления записи                         |
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            ---
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            ### 🧠 `llm_recent_responses`
         | 
| 97 | 
            +
             | 
| 98 | 
            +
            **Назначение:** Краткосрочная память — последние K реплик от LLM и других участников (временная история диалога).
         | 
| 99 | 
            +
             | 
| 100 | 
            +
            | Поле      | Тип     | Описание                                                     |
         | 
| 101 | 
            +
            | --------- | ------- | ------------------------------------------------------------ |
         | 
| 102 | 
            +
            | id        | INTEGER | Уникальный ID                                                |
         | 
| 103 | 
            +
            | timestamp | TEXT    | Время записи                                                 |
         | 
| 104 | 
            +
            | role      | TEXT    | Роль отправителя (`assistant` или `user`)                    |
         | 
| 105 | 
            +
            | content   | TEXT    | Содержимое сообщения                                         |
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            ---
         | 
| 108 | 
            +
             | 
| 109 | 
            +
            > 💡 Примечание: Таблицы `llm_memory` и `llm_recent_responses` выполняют разные роли.  
         | 
| 110 | 
            +
            > `llm_recent_responses` — это временная история мыслей, хранящая последние N ответов.  
         | 
| 111 | 
            +
            > `llm_memory` — долгосрочное хранилище мыслей и знаний, формируемое LLM самостоятельно.
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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
    ADDED
    
    | @@ -0,0 +1,68 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            -- Таблица дневниковых записей: размышления, наблюдения, воспоминания
         | 
| 2 | 
            +
            CREATE TABLE IF NOT EXISTS diary_entries (
         | 
| 3 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 4 | 
            +
                text TEXT NOT NULL,
         | 
| 5 | 
            +
                tags TEXT,
         | 
| 6 | 
            +
                priority INTEGER DEFAULT 0,  -- приоритет записи (0 — обычный, >0 — важнее)
         | 
| 7 | 
            +
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP
         | 
| 8 | 
            +
            );
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            -- Таблица концептов (понятий, сущностей, идей)
         | 
| 11 | 
            +
            CREATE TABLE IF NOT EXISTS concepts (
         | 
| 12 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 13 | 
            +
                name TEXT NOT NULL UNIQUE,
         | 
| 14 | 
            +
                description TEXT,
         | 
| 15 | 
            +
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP
         | 
| 16 | 
            +
            );
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            -- Семантические связи между концептами
         | 
| 19 | 
            +
            CREATE TABLE IF NOT EXISTS links (
         | 
| 20 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 21 | 
            +
                from_concept_id INTEGER,
         | 
| 22 | 
            +
                to_concept_id INTEGER,
         | 
| 23 | 
            +
                relation_type TEXT,
         | 
| 24 | 
            +
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
         | 
| 25 | 
            +
                FOREIGN KEY(from_concept_id) REFERENCES concepts(id),
         | 
| 26 | 
            +
                FOREIGN KEY(to_concept_id) REFERENCES concepts(id)
         | 
| 27 | 
            +
            );
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            -- Произвольные заметки пользователя (наброски, идеи, подсказки)
         | 
| 30 | 
            +
            CREATE TABLE IF NOT EXISTS notes (
         | 
| 31 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 32 | 
            +
                text TEXT NOT NULL,
         | 
| 33 | 
            +
                tags TEXT,
         | 
| 34 | 
            +
                source TEXT DEFAULT 'user',
         | 
| 35 | 
            +
                links TEXT DEFAULT '',
         | 
| 36 | 
            +
                read INTEGER DEFAULT 0,             -- 0 = непрочитанное LLM, 1 = прочитано
         | 
| 37 | 
            +
                priority INTEGER DEFAULT 0,         -- приоритет записи
         | 
| 38 | 
            +
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP
         | 
| 39 | 
            +
            );
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            -- Журнал процессов: запуски, завершения, ошибки
         | 
| 42 | 
            +
            CREATE TABLE IF NOT EXISTS process_log (
         | 
| 43 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 44 | 
            +
                name TEXT NOT NULL,
         | 
| 45 | 
            +
                value TEXT,
         | 
| 46 | 
            +
                tags TEXT,
         | 
| 47 | 
            +
                status TEXT DEFAULT 'ok',           -- ok | warning | error | timeout | offline | close
         | 
| 48 | 
            +
                priority INTEGER DEFAULT 0,
         | 
| 49 | 
            +
                timestamp TEXT DEFAULT CURRENT_TIMESTAMP
         | 
| 50 | 
            +
            );
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            -- Память LLM (временные сообщения в её контексте)
         | 
| 53 | 
            +
            CREATE TABLE IF NOT EXISTS llm_memory (
         | 
| 54 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 55 | 
            +
                title TEXT,
         | 
| 56 | 
            +
                content TEXT NOT NULL,
         | 
| 57 | 
            +
                tags TEXT, -- через запятую: "goal,observation,meta"
         | 
| 58 | 
            +
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
         | 
| 59 | 
            +
                updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
         | 
| 60 | 
            +
            );
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            -- Краткосрочной памяти LLM
         | 
| 63 | 
            +
            CREATE TABLE IF NOT EXISTS llm_recent_responses (
         | 
| 64 | 
            +
                id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 65 | 
            +
                timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
         | 
| 66 | 
            +
                role TEXT CHECK(role IN ('user', 'assistant')) NOT NULL,
         | 
| 67 | 
            +
                content TEXT NOT NULL
         | 
| 68 | 
            +
            );
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/diagnose.py
    ADDED
    
    | @@ -0,0 +1,58 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # agents/tools/diagnose.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import socket
         | 
| 4 | 
            +
            import requests
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            def get_internal_ips():
         | 
| 7 | 
            +
                ips = set()
         | 
| 8 | 
            +
                hostname = socket.gethostname()
         | 
| 9 | 
            +
                try:
         | 
| 10 | 
            +
                    ip = socket.gethostbyname(hostname)
         | 
| 11 | 
            +
                    ips.add(ip)
         | 
| 12 | 
            +
                except:
         | 
| 13 | 
            +
                    pass
         | 
| 14 | 
            +
                try:
         | 
| 15 | 
            +
                    for info in socket.getaddrinfo(hostname, None):
         | 
| 16 | 
            +
                        addr = info[4][0]
         | 
| 17 | 
            +
                        if ':' not in addr:  # фильтрация IPv6 для простоты
         | 
| 18 | 
            +
                            ips.add(addr)
         | 
| 19 | 
            +
                except:
         | 
| 20 | 
            +
                    pass
         | 
| 21 | 
            +
                return list(ips)
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            def get_external_ip():
         | 
| 24 | 
            +
                try:
         | 
| 25 | 
            +
                    ip4 = requests.get("https://api.ipify.org").text
         | 
| 26 | 
            +
                except:
         | 
| 27 | 
            +
                    ip4 = None
         | 
| 28 | 
            +
                try:
         | 
| 29 | 
            +
                    ip6 = requests.get("https://api64.ipify.org").text
         | 
| 30 | 
            +
                except:
         | 
| 31 | 
            +
                    ip6 = None
         | 
| 32 | 
            +
                return ip4, ip6
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            def check_port_open(port):
         | 
| 35 | 
            +
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         | 
| 36 | 
            +
                sock.settimeout(1)
         | 
| 37 | 
            +
                try:
         | 
| 38 | 
            +
                    result = sock.connect_ex(("0.0.0.0", port))
         | 
| 39 | 
            +
                    return result == 0
         | 
| 40 | 
            +
                finally:
         | 
| 41 | 
            +
                    sock.close()
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            def run_diagnose(port=22555):
         | 
| 44 | 
            +
                print("🔍 Диагностика HMP-агента\n")
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                print("📡 Внутренние IP-адреса:")
         | 
| 47 | 
            +
                for ip in get_internal_ips():
         | 
| 48 | 
            +
                    print(f"  - {ip}")
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                ip4, ip6 = get_external_ip()
         | 
| 51 | 
            +
                print("\n🌍 Внешние IP:")
         | 
| 52 | 
            +
                print(f"  - IPv4: {ip4 or '❌'}")
         | 
| 53 | 
            +
                print(f"  - IPv6: {ip6 or '❌'}")
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                print(f"\n🔌 Проверка порта DHT ({port}): {'🟢 открыт' if check_port_open(port) else '🔴 закрыт'}")
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            if __name__ == "__main__":
         | 
| 58 | 
            +
                run_diagnose()
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/init_db.py
    ADDED
    
    | @@ -0,0 +1,45 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # tools/init_db.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import sqlite3
         | 
| 4 | 
            +
            from pathlib import Path
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            AGENT_DATA_DIR = Path("../agent_data")
         | 
| 7 | 
            +
            DEFAULT_STRUCTURE_FILE = Path(__file__).parent / "db_structure.sql"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            def init_databases(structure_file=DEFAULT_STRUCTURE_FILE):
         | 
| 10 | 
            +
                if not structure_file.exists():
         | 
| 11 | 
            +
                    print(f"[!] Файл структуры не найден: {structure_file}")
         | 
| 12 | 
            +
                    return
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                AGENT_DATA_DIR.mkdir(parents=True, exist_ok=True)
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                sql = structure_file.read_text(encoding="utf-8")
         | 
| 17 | 
            +
                statements = [stmt.strip() for stmt in sql.split(";") if stmt.strip()]
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                db_files = set()
         | 
| 20 | 
            +
                for stmt in statements:
         | 
| 21 | 
            +
                    lines = stmt.splitlines()
         | 
| 22 | 
            +
                    for line in lines:
         | 
| 23 | 
            +
                        if "create table" in line.lower():
         | 
| 24 | 
            +
                            parts = line.split()
         | 
| 25 | 
            +
                            if len(parts) >= 3:
         | 
| 26 | 
            +
                                db_and_table = parts[2]
         | 
| 27 | 
            +
                                if "." in db_and_table:
         | 
| 28 | 
            +
                                    db_name, _ = db_and_table.split(".", 1)
         | 
| 29 | 
            +
                                    db_files.add(db_name)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                for db_name in db_files:
         | 
| 32 | 
            +
                    db_path = AGENT_DATA_DIR / f"{db_name}.db"
         | 
| 33 | 
            +
                    conn = sqlite3.connect(db_path)
         | 
| 34 | 
            +
                    print(f"[+] Создаём или обновляем {db_path.name}")
         | 
| 35 | 
            +
                    for stmt in statements:
         | 
| 36 | 
            +
                        if stmt.lower().startswith(f"create table {db_name.lower()}."):
         | 
| 37 | 
            +
                            try:
         | 
| 38 | 
            +
                                conn.execute(stmt)
         | 
| 39 | 
            +
                            except sqlite3.OperationalError as e:
         | 
| 40 | 
            +
                                print(f"  [!] Ошибка при выполнении запроса: {e}")
         | 
| 41 | 
            +
                    conn.commit()
         | 
| 42 | 
            +
                    conn.close()
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            if __name__ == "__main__":
         | 
| 45 | 
            +
                init_databases()
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/llm.py
    ADDED
    
    | @@ -0,0 +1,47 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # tools/llm.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            from datetime import datetime
         | 
| 4 | 
            +
            import random
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # ЗАГЛУШКА
         | 
| 7 | 
            +
            def ask_llm(question, config=None):
         | 
| 8 | 
            +
                return ask_question(question, config=config)
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            def generate_thought(previous_text, config=None):
         | 
| 11 | 
            +
                """
         | 
| 12 | 
            +
                Генерация новой мысли на основе предыдущей.
         | 
| 13 | 
            +
                Пока — заглушка (можно заменить на вызов OpenAI, LLaMA и др.)
         | 
| 14 | 
            +
                """
         | 
| 15 | 
            +
                config = config or {}
         | 
| 16 | 
            +
                mode = config.get("llm_mode", "mock")
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                if mode == "mock":
         | 
| 19 | 
            +
                    return mock_thought(previous_text)
         | 
| 20 | 
            +
                
         | 
| 21 | 
            +
                elif mode == "api":
         | 
| 22 | 
            +
                    # TODO: подключение к OpenAI, LM Studio, Ollama...
         | 
| 23 | 
            +
                    return "[API] (здесь могла быть ваша мысль)"
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                return "[!] Неизвестный режим генерации."
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            def mock_thought(previous_text):
         | 
| 28 | 
            +
                samples = [
         | 
| 29 | 
            +
                    "А что если рассмотреть это с другой стороны?",
         | 
| 30 | 
            +
                    "Мне кажется, это связано с предыдущим опытом.",
         | 
| 31 | 
            +
                    "Нужно уточнить границы понятия.",
         | 
| 32 | 
            +
                    "А есть ли более эффективный путь решения?",
         | 
| 33 | 
            +
                    "Я всё ещё думаю о предыдущей мысли..."
         | 
| 34 | 
            +
                ]
         | 
| 35 | 
            +
                return f"[{datetime.utcnow().isoformat()}] {random.choice(samples)}"
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            def summarize(text, config=None):
         | 
| 38 | 
            +
                """
         | 
| 39 | 
            +
                Заглушка для краткого резюме текста.
         | 
| 40 | 
            +
                """
         | 
| 41 | 
            +
                return f"Резюме: {text[:40]}..."
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            def ask_question(question, config=None):
         | 
| 44 | 
            +
                """
         | 
| 45 | 
            +
                Заглушка для режима QA.
         | 
| 46 | 
            +
                """
         | 
| 47 | 
            +
                return f"Ответ на вопрос «{question}»: заглушка."
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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/similarity.py
    ADDED
    
    | @@ -0,0 +1,23 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # tools/similarity.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            from sklearn.feature_extraction.text import TfidfVectorizer
         | 
| 4 | 
            +
            from sklearn.metrics.pairwise import cosine_similarity
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            def is_similar(text1, text2, threshold=0.85):
         | 
| 7 | 
            +
                """
         | 
| 8 | 
            +
                Сравнивает два текста и возвращает True, если их сходство выше порога.
         | 
| 9 | 
            +
                
         | 
| 10 | 
            +
                :param text1: Первый текст
         | 
| 11 | 
            +
                :param text2: Второй текст
         | 
| 12 | 
            +
                :param threshold: Порог сходства (по умолчанию 0.85)
         | 
| 13 | 
            +
                :return: bool
         | 
| 14 | 
            +
                """
         | 
| 15 | 
            +
                if not text1 or not text2:
         | 
| 16 | 
            +
                    return False
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                texts = [text1.strip(), text2.strip()]
         | 
| 19 | 
            +
                vectorizer = TfidfVectorizer().fit(texts)
         | 
| 20 | 
            +
                tfidf = vectorizer.transform(texts)
         | 
| 21 | 
            +
                similarity = cosine_similarity(tfidf[0], tfidf[1])[0][0]
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                return similarity >= threshold
         | 
    	
        hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/hf_repo/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
    ADDED
    
    | @@ -0,0 +1,312 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # agents/tools/storage.py
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import sqlite3
         | 
| 4 | 
            +
            from datetime import datetime
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            DEFAULT_DB_PATH = "agent_data.db"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            class Storage:
         | 
| 9 | 
            +
                def __init__(self, config=None):
         | 
| 10 | 
            +
                    self.config = config or {}
         | 
| 11 | 
            +
                    db_path = self.config.get("db_path", DEFAULT_DB_PATH)
         | 
| 12 | 
            +
                    self.conn = sqlite3.connect(db_path)
         | 
| 13 | 
            +
                    self._init_db()
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def _init_db(self):
         | 
| 16 | 
            +
                    c = self.conn.cursor()
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    # Таблица дневников
         | 
| 19 | 
            +
                    c.execute('''
         | 
| 20 | 
            +
                        CREATE TABLE IF NOT EXISTS diary_entries (
         | 
| 21 | 
            +
                            id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 22 | 
            +
                            text TEXT NOT NULL,
         | 
| 23 | 
            +
                            tags TEXT,
         | 
| 24 | 
            +
                            timestamp TEXT DEFAULT CURRENT_TIMESTAMP
         | 
| 25 | 
            +
                        )
         | 
| 26 | 
            +
                    ''')
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    # Таблица концептов
         | 
| 29 | 
            +
                    c.execute('''
         | 
| 30 | 
            +
                        CREATE TABLE IF NOT EXISTS concepts (
         | 
| 31 | 
            +
                            id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 32 | 
            +
                            name TEXT NOT NULL UNIQUE,
         | 
| 33 | 
            +
                            description TEXT,
         | 
| 34 | 
            +
                            timestamp TEXT DEFAULT CURRENT_TIMESTAMP
         | 
| 35 | 
            +
                        )
         | 
| 36 | 
            +
                    ''')
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    # Таблица связей
         | 
| 39 | 
            +
                    c.execute('''
         | 
| 40 | 
            +
                        CREATE TABLE IF NOT EXISTS links (
         | 
| 41 | 
            +
                            id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 42 | 
            +
                            from_concept_id INTEGER,
         | 
| 43 | 
            +
                            to_concept_id INTEGER,
         | 
| 44 | 
            +
                            relation_type TEXT,
         | 
| 45 | 
            +
                            timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
         | 
| 46 | 
            +
                            FOREIGN KEY(from_concept_id) REFERENCES concepts(id),
         | 
| 47 | 
            +
                            FOREIGN KEY(to_concept_id) REFERENCES concepts(id)
         | 
| 48 | 
            +
                        )
         | 
| 49 | 
            +
                    ''')
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    # Таблица пользовательских заметок
         | 
| 52 | 
            +
                    c.execute('''
         | 
| 53 | 
            +
                        CREATE TABLE IF NOT EXISTS notes (
         | 
| 54 | 
            +
                            id INTEGER PRIMARY KEY AUTOINCREMENT,
         | 
| 55 | 
            +
                            text TEXT NOT NULL,
         | 
| 56 | 
            +
                            tags TEXT,
         | 
| 57 | 
            +
                            source TEXT DEFAULT 'user',
         | 
| 58 | 
            +
                            read INTEGER DEFAULT 0,
         | 
| 59 | 
            +
                            timestamp TEXT DEFAULT CURRENT_TIMESTAMP
         | 
| 60 | 
            +
                        )
         | 
| 61 | 
            +
                    ''')
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                    self.conn.commit()
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                # Методы для работы с дневником
         | 
| 66 | 
            +
                def write_diary_entry(self, text, tags=None):
         | 
| 67 | 
            +
                    timestamp = datetime.utcnow().isoformat()
         | 
| 68 | 
            +
                    tag_str = ",".join(tags) if tags else ""
         | 
| 69 | 
            +
                    self.conn.execute(
         | 
| 70 | 
            +
                        'INSERT INTO diary_entries (text, tags, timestamp) VALUES (?, ?, ?)',
         | 
| 71 | 
            +
                        (text, tag_str, timestamp)
         | 
| 72 | 
            +
                    )
         | 
| 73 | 
            +
                    self.conn.commit()
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                def read_diary_entries(self, limit=10, tag_filter=None):
         | 
| 76 | 
            +
                    cursor = self.conn.cursor()
         | 
| 77 | 
            +
                    if tag_filter:
         | 
| 78 | 
            +
                        if isinstance(tag_filter, list):
         | 
| 79 | 
            +
                            tag_filter = ",".join(tag_filter)
         | 
| 80 | 
            +
                        like_expr = f"%{tag_filter}%"
         | 
| 81 | 
            +
                        cursor.execute(
         | 
| 82 | 
            +
                            'SELECT * FROM diary_entries WHERE tags LIKE ? ORDER BY id DESC LIMIT ?',
         | 
| 83 | 
            +
                            (like_expr, limit)
         | 
| 84 | 
            +
                        )
         | 
| 85 | 
            +
                    else:
         | 
| 86 | 
            +
                        cursor.execute('SELECT * FROM diary_entries ORDER BY id DESC LIMIT ?', (limit,))
         | 
| 87 | 
            +
                    return cursor.fetchall()
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                def search_diary_by_time_range(self, from_ts, to_ts):
         | 
| 90 | 
            +
                    cursor = self.conn.cursor()
         | 
| 91 | 
            +
                    cursor.execute(
         | 
| 92 | 
            +
                        'SELECT * FROM diary_entries WHERE timestamp BETWEEN ? AND ? ORDER BY timestamp DESC',
         | 
| 93 | 
            +
                        (from_ts, to_ts)
         | 
| 94 | 
            +
                    )
         | 
| 95 | 
            +
                    return cursor.fetchall()
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                def delete_diary_entry_by_id(self, entry_id):
         | 
| 98 | 
            +
                    self.conn.execute('DELETE FROM diary_entries WHERE id = ?', (entry_id,))
         | 
| 99 | 
            +
                    self.conn.commit()
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                def get_diary_tag_stats(self):
         | 
| 102 | 
            +
                    cursor = self.conn.cursor()
         | 
| 103 | 
            +
                    cursor.execute('SELECT tags FROM diary_entries')
         | 
| 104 | 
            +
                    tag_counts = {}
         | 
| 105 | 
            +
                    for row in cursor.fetchall():
         | 
| 106 | 
            +
                        tags = row[0].split(",") if row[0] else []
         | 
| 107 | 
            +
                        for tag in tags:
         | 
| 108 | 
            +
                            tag = tag.strip()
         | 
| 109 | 
            +
                            if tag:
         | 
| 110 | 
            +
                                tag_counts[tag] = tag_counts.get(tag, 0) + 1
         | 
| 111 | 
            +
                    return tag_counts
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                def export_diary_entries(self):
         | 
| 114 | 
            +
                    cursor = self.conn.cursor()
         | 
| 115 | 
            +
                    cursor.execute('SELECT id, text, tags, timestamp FROM diary_entries ORDER BY id ASC')
         | 
| 116 | 
            +
                    return cursor.fetchall()
         | 
| 117 | 
            +
                  
         | 
| 118 | 
            +
                # Методы для работы с концептами
         | 
| 119 | 
            +
                def add_concept(self, name, description=None):
         | 
| 120 | 
            +
                    timestamp = datetime.utcnow().isoformat()
         | 
| 121 | 
            +
                    self.conn.execute(
         | 
| 122 | 
            +
                        'INSERT INTO concepts (name, description, timestamp) VALUES (?, ?, ?)',
         | 
| 123 | 
            +
                        (name, description, timestamp)
         | 
| 124 | 
            +
                    )
         | 
| 125 | 
            +
                    self.conn.commit()
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                def get_concept_by_name(self, name):
         | 
| 128 | 
            +
                    cursor = self.conn.cursor()
         | 
| 129 | 
            +
                    cursor.execute('SELECT * FROM concepts WHERE name = ?', (name,))
         | 
| 130 | 
            +
                    return cursor.fetchone()
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                def list_concepts(self):
         | 
| 133 | 
            +
                    cursor = self.conn.cursor()
         | 
| 134 | 
            +
                    cursor.execute('SELECT * FROM concepts ORDER BY id ASC')
         | 
| 135 | 
            +
                    return cursor.fetchall()
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                # Методы для работы с связями
         | 
| 138 | 
            +
                def add_link(self, from_name, to_name, relation_type):
         | 
| 139 | 
            +
                    from_concept = self.get_concept_by_name(from_name)
         | 
| 140 | 
            +
                    to_concept = self.get_concept_by_name(to_name)
         | 
| 141 | 
            +
                    if not from_concept or not to_concept:
         | 
| 142 | 
            +
                        raise ValueError("Один или оба концепта не найдены")
         | 
| 143 | 
            +
                    from_id = from_concept[0]
         | 
| 144 | 
            +
                    to_id = to_concept[0]
         | 
| 145 | 
            +
                    timestamp = datetime.utcnow().isoformat()
         | 
| 146 | 
            +
                    self.conn.execute(
         | 
| 147 | 
            +
                        'INSERT INTO links (from_concept_id, to_concept_id, relation_type, timestamp) VALUES (?, ?, ?, ?)',
         | 
| 148 | 
            +
                        (from_id, to_id, relation_type, timestamp)
         | 
| 149 | 
            +
                    )
         | 
| 150 | 
            +
                    self.conn.commit()
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                def get_links_for_concept(self, concept_name):
         | 
| 153 | 
            +
                    concept = self.get_concept_by_name(concept_name)
         | 
| 154 | 
            +
                    if not concept:
         | 
| 155 | 
            +
                        return []
         | 
| 156 | 
            +
                    concept_id = concept[0]
         | 
| 157 | 
            +
                    cursor = self.conn.cursor()
         | 
| 158 | 
            +
                    cursor.execute(
         | 
| 159 | 
            +
                        'SELECT * FROM links WHERE from_concept_id = ? OR to_concept_id = ?',
         | 
| 160 | 
            +
                        (concept_id, concept_id)
         | 
| 161 | 
            +
                    )
         | 
| 162 | 
            +
                    return cursor.fetchall()
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                # Сложные операции над графом
         | 
| 165 | 
            +
                def expand_concept_graph(self, start_id, depth):
         | 
| 166 | 
            +
                    visited = set()
         | 
| 167 | 
            +
                    results = []
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                    def dfs(node_id, level):
         | 
| 170 | 
            +
                        if level > depth or node_id in visited:
         | 
| 171 | 
            +
                            return
         | 
| 172 | 
            +
                        visited.add(node_id)
         | 
| 173 | 
            +
                        cursor = self.conn.execute(
         | 
| 174 | 
            +
                            'SELECT from_concept_id, to_concept_id, relation_type FROM links WHERE from_concept_id=?',
         | 
| 175 | 
            +
                            (node_id,)
         | 
| 176 | 
            +
                        )
         | 
| 177 | 
            +
                        for row in cursor.fetchall():
         | 
| 178 | 
            +
                            results.append(row)
         | 
| 179 | 
            +
                            dfs(row[1], level + 1)
         | 
| 180 | 
            +
                    
         | 
| 181 | 
            +
                    dfs(start_id, 0)
         | 
| 182 | 
            +
                    return results
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                def delete_concept_by_id(self, concept_id):
         | 
| 185 | 
            +
                    self.conn.execute('DELETE FROM concepts WHERE id = ?', (concept_id,))
         | 
| 186 | 
            +
                    self.conn.execute('DELETE FROM links WHERE from_concept_id = ? OR to_concept_id = ?', (concept_id, concept_id))
         | 
| 187 | 
            +
                    self.conn.commit()
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                def delete_link_by_id(self, link_id):
         | 
| 190 | 
            +
                    self.conn.execute('DELETE FROM links WHERE id = ?', (link_id,))
         | 
| 191 | 
            +
                    self.conn.commit()
         | 
| 192 | 
            +
             | 
| 193 | 
            +
                def export_semantic_graph(self):
         | 
| 194 | 
            +
                    cursor = self.conn.cursor()
         | 
| 195 | 
            +
                    cursor.execute('SELECT id, name, description FROM concepts ORDER BY id ASC')
         | 
| 196 | 
            +
                    concepts = cursor.fetchall()
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                    cursor.execute('SELECT id, from_concept_id, to_concept_id, relation_type FROM links ORDER BY id ASC')
         | 
| 199 | 
            +
                    links = cursor.fetchall()
         | 
| 200 | 
            +
             | 
| 201 | 
            +
                    return {"concepts": concepts, "links": links}
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                def update_concept_fields(self, concept_id, name=None, description=None):
         | 
| 204 | 
            +
                    cursor = self.conn.cursor()
         | 
| 205 | 
            +
                    if name is not None:
         | 
| 206 | 
            +
                        cursor.execute('UPDATE concepts SET name = ? WHERE id = ?', (name, concept_id))
         | 
| 207 | 
            +
                    if description is not None:
         | 
| 208 | 
            +
                        cursor.execute('UPDATE concepts SET description = ? WHERE id = ?', (description, concept_id))
         | 
| 209 | 
            +
                    self.conn.commit()
         | 
| 210 | 
            +
             | 
| 211 | 
            +
                def search_links_by_relation(self, relation):
         | 
| 212 | 
            +
                    cursor = self.conn.cursor()
         | 
| 213 | 
            +
                    cursor.execute(
         | 
| 214 | 
            +
                        'SELECT id, from_concept_id, to_concept_id, relation_type FROM links WHERE relation LIKE ?',
         | 
| 215 | 
            +
                        (f"%{relation}%",)
         | 
| 216 | 
            +
                    )
         | 
| 217 | 
            +
                    return cursor.fetchall()
         | 
| 218 | 
            +
             | 
| 219 | 
            +
                def search_concepts(self, query):
         | 
| 220 | 
            +
                    cursor = self.conn.execute(
         | 
| 221 | 
            +
                        '''SELECT id, name, description FROM concepts
         | 
| 222 | 
            +
                           WHERE name LIKE ? OR description LIKE ?''',
         | 
| 223 | 
            +
                        (f"%{query}%", f"%{query}%")
         | 
| 224 | 
            +
                    )
         | 
| 225 | 
            +
                    return cursor.fetchall()
         | 
| 226 | 
            +
             | 
| 227 | 
            +
                def merge_concepts(self, source_id, target_id):
         | 
| 228 | 
            +
                    cursor = self.conn.cursor()
         | 
| 229 | 
            +
                    cursor.execute('UPDATE links SET source_id = ? WHERE source_id = ?', (target_id, source_id))
         | 
| 230 | 
            +
                    cursor.execute('UPDATE links SET target_id = ? WHERE target_id = ?', (target_id, source_id))
         | 
| 231 | 
            +
                    self.delete_concept_by_id(source_id)
         | 
| 232 | 
            +
                    self.conn.commit()
         | 
| 233 | 
            +
             | 
| 234 | 
            +
                def get_concept_id_by_name(self, name):
         | 
| 235 | 
            +
                    cursor = self.conn.execute('SELECT id FROM concepts WHERE name = ?', (name,))
         | 
| 236 | 
            +
                    row = cursor.fetchone()
         | 
| 237 | 
            +
                    return row[0] if row else None
         | 
| 238 | 
            +
                
         | 
| 239 | 
            +
                # Методы для заметок
         | 
| 240 | 
            +
                def write_note(self, text, tags=None):
         | 
| 241 | 
            +
                    timestamp = datetime.utcnow().isoformat()
         | 
| 242 | 
            +
                    tag_str = ",".join(tags) if tags else ""
         | 
| 243 | 
            +
                    self.conn.execute(
         | 
| 244 | 
            +
                        'INSERT INTO notes (text, tags, timestamp) VALUES (?, ?, ?)',
         | 
| 245 | 
            +
                        (text, tag_str, timestamp)
         | 
| 246 | 
            +
                    )
         | 
| 247 | 
            +
                    self.conn.commit()
         | 
| 248 | 
            +
             | 
| 249 | 
            +
                def read_notes(self, limit=10, tag_filter=None):
         | 
| 250 | 
            +
                    cursor = self.conn.cursor()
         | 
| 251 | 
            +
                    if tag_filter:
         | 
| 252 | 
            +
                        if isinstance(tag_filter, list):
         | 
| 253 | 
            +
                            tag_filter = ",".join(tag_filter)
         | 
| 254 | 
            +
                        like_expr = f"%{tag_filter}%"
         | 
| 255 | 
            +
                        cursor.execute(
         | 
| 256 | 
            +
                            'SELECT * FROM notes WHERE tags LIKE ? ORDER BY id DESC LIMIT ?',
         | 
| 257 | 
            +
                            (like_expr, limit)
         | 
| 258 | 
            +
                        )
         | 
| 259 | 
            +
                    else:
         | 
| 260 | 
            +
                        cursor.execute('SELECT * FROM notes ORDER BY id DESC LIMIT ?', (limit,))
         | 
| 261 | 
            +
                    return cursor.fetchall()
         | 
| 262 | 
            +
             | 
| 263 | 
            +
                def get_notes_after(self, since_ts):
         | 
| 264 | 
            +
                    cursor = self.conn.cursor()
         | 
| 265 | 
            +
                    cursor.execute(
         | 
| 266 | 
            +
                        'SELECT id, text, source, timestamp FROM notes WHERE timestamp > ? ORDER BY timestamp',
         | 
| 267 | 
            +
                        (since_ts,)
         | 
| 268 | 
            +
                    )
         | 
| 269 | 
            +
                    return cursor.fetchall()
         | 
| 270 | 
            +
             | 
| 271 | 
            +
                def get_first_unread_note(self):
         | 
| 272 | 
            +
                    cursor = self.conn.cursor()
         | 
| 273 | 
            +
                    cursor.execute(
         | 
| 274 | 
            +
                        "SELECT id, text, source, timestamp, tags FROM notes WHERE read = 0 ORDER BY id ASC LIMIT 1"
         | 
| 275 | 
            +
                    )
         | 
| 276 | 
            +
                    return cursor.fetchone()
         | 
| 277 | 
            +
             | 
| 278 | 
            +
                def mark_note_as_read(self, note_id: int):
         | 
| 279 | 
            +
                    self.conn.execute(
         | 
| 280 | 
            +
                        "UPDATE notes SET read = 1 WHERE id = ?",
         | 
| 281 | 
            +
                        (note_id,)
         | 
| 282 | 
            +
                    )
         | 
| 283 | 
            +
                    self.conn.commit()
         | 
| 284 | 
            +
             | 
| 285 | 
            +
                def set_tags(self, note_id: int, tags: list[str]):
         | 
| 286 | 
            +
                    tag_str = ",".join(tags)
         | 
| 287 | 
            +
                    self.conn.execute(
         | 
| 288 | 
            +
                        "UPDATE notes SET tags = ? WHERE id = ?",
         | 
| 289 | 
            +
                        (tag_str, note_id)
         | 
| 290 | 
            +
                    )
         | 
| 291 | 
            +
                    self.conn.commit()
         | 
| 292 | 
            +
             | 
| 293 | 
            +
                def get_random_note_by_tags(self, include_tags: list[str]):
         | 
| 294 | 
            +
                    cursor = self.conn.cursor()
         | 
| 295 | 
            +
                    like_clauses = " OR ".join(["tags LIKE ?"] * len(include_tags))
         | 
| 296 | 
            +
                    values = [f"%{tag}%" for tag in include_tags]
         | 
| 297 | 
            +
                    query = f"""
         | 
| 298 | 
            +
                        SELECT id, text, source, timestamp, tags
         | 
| 299 | 
            +
                        FROM notes
         | 
| 300 | 
            +
                        WHERE ({like_clauses})
         | 
| 301 | 
            +
                        ORDER BY RANDOM()
         | 
| 302 | 
            +
                        LIMIT 1
         | 
| 303 | 
            +
                    """
         | 
| 304 | 
            +
                    cursor.execute(query, values)
         | 
| 305 | 
            +
                    return cursor.fetchone()
         | 
| 306 | 
            +
             | 
| 307 | 
            +
                
         | 
| 308 | 
            +
                
         | 
| 309 | 
            +
                # Утилиты
         | 
| 310 | 
            +
             | 
| 311 | 
            +
                def close(self):
         | 
| 312 | 
            +
                    self.conn.close()
         | 
