From 8941582d5429d1ebbac6071722d1dd9e04f13f36b94e7cd09a736b929eb104f0 Mon Sep 17 00:00:00 2001 From: AidarKC Date: Mon, 25 May 2026 23:46:54 +0300 Subject: [PATCH] =?UTF-8?q?chore:=20=D0=B7=D0=B0=D1=84=D0=B8=D0=BA=D1=81?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D1=8B=20=D0=B2=D1=81=D0=B5?= =?UTF-8?q?=20=D1=82=D0=B5=D0=BA=D1=83=D1=89=D0=B8=D0=B5=20=D0=B8=D0=B7?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/vcs.xml | 2 + AGENTS.md | 14 +- Dev_Docs/Future_Features/README.md | 36 +- Dev_Docs/Future_Features/far/README.md | 5 + ...6-05-24_1140_репосты_в_каналах_и_тредах.md | 6 + .../2026-05-25_1106_shine_balance_wallet.md | 62 ++ ...26-05-25_1106_channels_my_create_button.md | 67 ++ .../2026-05-25_1106_telegram_agent_players.md | 94 +++ ...-05-25_1106_wallet_topup_solana_arweave.md | 71 +++ ...2026-05-24_2035_solana-init-registracii.md | 26 + ...5_1545_otchet_private_zaprosov_v_gruppu.md | 26 + .../2026-05-25_1556_voice_otchet_s_audio.md | 23 + ...2026-05-25_2057_voice_timeout_i_oshibki.md | 19 + Dev_Docs/Solana/user_pda/README.md | 6 +- Dev_Docs/Solana_Architecture/README.md | 166 +++++ .../details/accounts_and_money_flow.md | 110 ++++ .../Solana_Architecture/details/shine_dao.md | 74 +++ .../details/shine_login_guard.md | 58 ++ .../details/shine_payments.md | 173 ++++++ .../details/shine_users.md | 136 ++++ .../schemes/architecture.mmd | 54 ++ .../schemes/architecture.png | Bin 0 -> 239574 bytes .../schemes/architecture.svg | 139 +++++ .../README.md | 91 +++ Players/blackbyrd1/files/.gitkeep | 1 + Players/blackbyrd1/history/.gitkeep | 1 + Players/dimasol1/files/.gitkeep | 1 + Players/dimasol1/history/.gitkeep | 1 + Players/malvviiina/files/.gitkeep | 1 + Players/malvviiina/history/.gitkeep | 1 + Players/oidasyda/files/.gitkeep | 1 + Players/oidasyda/history/.gitkeep | 1 + Players/zodiaktechnika32/files/.gitkeep | 1 + Players/zodiaktechnika32/history/.gitkeep | 1 + SHiNE-agent-bot-coder/.env.example | 3 + SHiNE-agent-bot-coder/AGENT.md | 28 +- SHiNE-agent-bot-coder/AGENTS.md | 25 + .../Players/PROMPTS_REVIEW.md | 26 + SHiNE-agent-bot-coder/README.md | 13 +- SHiNE-agent-bot-coder/py_bot_service.py | 588 +++++++++++++++--- shine-UI/js/app.js | 2 + shine-UI/js/pages/developer-settings-view.js | 3 + shine-UI/js/pages/solana-users-init-view.js | 196 ++++++ shine-UI/js/router.js | 3 +- shine-UI/js/services/solana-wallet-service.js | 3 +- shine-UI/js/solana-programs.js | 8 + shine-UI/js/state.js | 3 +- .../utils/config/SolanaProgramsConfig.java | 21 + .../Net_GetMessageThread_Handler.java | 5 + .../Net_GetMessageThread_Response.java | 4 + .../shine/doc/SHiNE-user-format-v.1.0.md | 6 +- .../shine/programs/shine_users/src/users.rs | 2 +- shine-solana/shine/tests/shine.ts | 2 +- 53 files changed, 2303 insertions(+), 106 deletions(-) create mode 100644 Dev_Docs/Future_Features/far/README.md rename Dev_Docs/Future_Features/{ => medium}/2026-05-24_1140_репосты_в_каналах_и_тредах.md (99%) create mode 100644 Dev_Docs/Future_Features/medium/2026-05-25_1106_shine_balance_wallet.md create mode 100644 Dev_Docs/Future_Features/near/2026-05-25_1106_channels_my_create_button.md create mode 100644 Dev_Docs/Future_Features/near/2026-05-25_1106_telegram_agent_players.md create mode 100644 Dev_Docs/Future_Features/near/2026-05-25_1106_wallet_topup_solana_arweave.md create mode 100644 Dev_Docs/Pending_Features/2026-05-24_2035_solana-init-registracii.md create mode 100644 Dev_Docs/Pending_Features/2026-05-25_1545_otchet_private_zaprosov_v_gruppu.md create mode 100644 Dev_Docs/Pending_Features/2026-05-25_1556_voice_otchet_s_audio.md create mode 100644 Dev_Docs/Pending_Features/2026-05-25_2057_voice_timeout_i_oshibki.md create mode 100644 Dev_Docs/Solana_Architecture/README.md create mode 100644 Dev_Docs/Solana_Architecture/details/accounts_and_money_flow.md create mode 100644 Dev_Docs/Solana_Architecture/details/shine_dao.md create mode 100644 Dev_Docs/Solana_Architecture/details/shine_login_guard.md create mode 100644 Dev_Docs/Solana_Architecture/details/shine_payments.md create mode 100644 Dev_Docs/Solana_Architecture/details/shine_users.md create mode 100644 Dev_Docs/Solana_Architecture/schemes/architecture.mmd create mode 100644 Dev_Docs/Solana_Architecture/schemes/architecture.png create mode 100644 Dev_Docs/Solana_Architecture/schemes/architecture.svg create mode 100644 Dev_Docs/Инициализация_Solana_регистрации/README.md create mode 100644 Players/blackbyrd1/files/.gitkeep create mode 100644 Players/blackbyrd1/history/.gitkeep create mode 100644 Players/dimasol1/files/.gitkeep create mode 100644 Players/dimasol1/history/.gitkeep create mode 100644 Players/malvviiina/files/.gitkeep create mode 100644 Players/malvviiina/history/.gitkeep create mode 100644 Players/oidasyda/files/.gitkeep create mode 100644 Players/oidasyda/history/.gitkeep create mode 100644 Players/zodiaktechnika32/files/.gitkeep create mode 100644 Players/zodiaktechnika32/history/.gitkeep create mode 100644 SHiNE-agent-bot-coder/AGENTS.md create mode 100644 SHiNE-agent-bot-coder/Players/PROMPTS_REVIEW.md create mode 100644 shine-UI/js/pages/solana-users-init-view.js create mode 100644 shine-UI/js/solana-programs.js create mode 100644 shine-server-config/src/main/java/utils/config/SolanaProgramsConfig.java diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 0faa797..5044830 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,7 @@ + + \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index eb82179..afe8a83 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,7 +11,9 @@ ## Сервис агента-кодера - В проекте есть локальный Telegram-бот-сервис агента-кодера в папке `SHiNE-agent-bot-coder/`. - Сервис принимает сообщения из Telegram, ведёт историю диалога, ставит задачи в очередь и вызывает Codex CLI для обработки запросов по проекту. -- Подробные правила работы сервиса, его очередь, история, systemd-запуск и особенности ответов описывать в `SHiNE-agent-bot-coder/AGENT.md`. +- Автоматически читаемые инструкции для Codex внутри сервиса держать в `SHiNE-agent-bot-coder/AGENTS.md`. +- Подробные служебные правила Telegram-обработчика, его очередь, история, systemd-запуск и особенности ответов описывать в `SHiNE-agent-bot-coder/AGENT.md`. +- Если в сообщениях пользователя встречается «агент MD» или похожая формулировка про файл инструкций Codex, считать, что имеется в виду автоматически читаемый `AGENTS.md`. ## Solana-модуль - В проекте есть отдельный Solana/Anchor-модуль в папке `shine-solana/shine/`. @@ -19,6 +21,13 @@ - В Solana-модуле действуют локальные инструкции `shine-solana/shine/AGENTS.md`; при изменениях внутри модуля сначала читать их. - В git добавлять исходники, lock-файлы, настройки проекта и документацию Solana-модуля, но не добавлять локальные ключи, `.git`, `.idea`, `.gradle`, `target`, `node_modules`, `test-ledger`, логи, временные run-отчёты и `.env`-конфиги. - Для Solana deploy/push использовать правила из локального `shine-solana/shine/AGENTS.md`; не смешивать deploy Solana-модуля с `deployServer`/`deployUI` основного проекта. +- Для регистрации пользователей в Solana (программа `shine_users`) единая актуальная инструкция по деплою/инициализации, адресам программ, и куда их прописывать в UI/сервере находится в: + - `Dev_Docs/Инициализация_Solana_регистрации/README.md` +- Этот файл считать основной справкой (single source of truth) по деплою и первичной инициализации Solana-регистрации в текущем проекте. +- Актуальная архитектурная справка по устройству Solana-программ, PDA-счетам, ролям DAO и движению средств находится в: + - `Dev_Docs/Solana_Architecture/README.md` +- Документ формата пользовательской PDA-записи `shine_users` находится в: + - `shine-solana/shine/doc/SHiNE-user-format-v.1.0.md` ## Документация блокчейна - Актуальная документация по форматам блокчейна находится в `Dev_Docs/Blockchain/README.md`. @@ -99,6 +108,9 @@ ## Будущие фичи - Папка для задач, сознательно отложенных на будущее: `Dev_Docs/Future_Features/`. +- Точка входа по планам: `Dev_Docs/Future_Features/README.md`. +- Внутри планы разделены по горизонтам: `near/`, `medium/`, `far/`. +- Если пользователь спрашивает, какие есть планы или что можно продолжить, сначала читать `Dev_Docs/Future_Features/README.md`, затем при необходимости конкретные файлы из горизонтов. - Файлы из этой папки не считать активными задачами и не начинать реализацию без явной просьбы пользователя. - Если часть кода временно отключена или закомментирована, в файле будущей фичи подробно описывать: - какие файлы и участки отключены; diff --git a/Dev_Docs/Future_Features/README.md b/Dev_Docs/Future_Features/README.md index 6a51e70..999140e 100644 --- a/Dev_Docs/Future_Features/README.md +++ b/Dev_Docs/Future_Features/README.md @@ -1,14 +1,42 @@ # Будущие фичи -Эта папка хранит задачи, которые сознательно отложены и сейчас не должны попадать в активную разработку или ручную проверку. +Эта папка хранит задачи, которые сознательно отложены и сейчас не должны попадать в активную разработку или ручную проверку без отдельной команды пользователя. + +## Горизонты планирования + +- `near/` - ближайшие планы: задачи, к которым можно вернуться сегодня или завтра. +- `medium/` - среднесрочные планы: задачи на ближайшие недели или 1-2 месяца. +- `far/` - дальнее будущее: идеи без понятного срока возврата. + +Если пользователь спрашивает, какие есть планы, агент должен смотреть эти три папки и кратко перечислять задачи по горизонтам. ## Как использовать -1. Каждая будущая фича описывается отдельным markdown-файлом. +1. Каждая будущая фича описывается отдельным markdown-файлом в одном из горизонтов. 2. В файле нужно фиксировать: - зачем нужна фича; - - что уже было сделано в коде; - - что временно отключено или закомментировано; + - к какому сроку или горизонту она относится; + - что нужно сделать; + - какие вопросы нужно уточнить перед реализацией; + - что уже было сделано в коде, если фича частично реализована; + - что временно отключено или закомментировано, если применимо; - какие документы нужно обновить при возврате к задаче; - с какого места продолжать разработку. 3. Агент не должен начинать реализацию файлов из этой папки без явной просьбы пользователя. + +## Текущие планы + +### Ближайшие + +- `near/2026-05-25_1106_telegram_agent_players.md` - разрешённые пользователи Telegram для агента, отдельные папки игроков, персональные истории и публикация краткого вопроса/ответа в общий канал. +- `near/2026-05-25_1106_wallet_topup_solana_arweave.md` - пополнение Solana и Arweave через внешний сервис покупки с подсказкой и копированием адреса. +- `near/2026-05-25_1106_channels_my_create_button.md` - поправить экран каналов: создание канала показывать только в разделе `Мои каналы`. + +### Среднесрочные + +- `medium/2026-05-24_1140_репосты_в_каналах_и_тредах.md` - репосты в каналах и тредах. +- `medium/2026-05-25_1106_shine_balance_wallet.md` - кошелёк и пополнение баланса сияния через блокчейн. + +### Дальнее будущее + +- Сейчас задач нет. diff --git a/Dev_Docs/Future_Features/far/README.md b/Dev_Docs/Future_Features/far/README.md new file mode 100644 index 0000000..5dc5d98 --- /dev/null +++ b/Dev_Docs/Future_Features/far/README.md @@ -0,0 +1,5 @@ +# Дальнее будущее + +Сейчас в этом горизонте нет активных идей. + +Сюда переносить задачи, у которых нет понятного срока возврата и которые не нужно учитывать в ближайшем или среднесрочном планировании. diff --git a/Dev_Docs/Future_Features/2026-05-24_1140_репосты_в_каналах_и_тредах.md b/Dev_Docs/Future_Features/medium/2026-05-24_1140_репосты_в_каналах_и_тредах.md similarity index 99% rename from Dev_Docs/Future_Features/2026-05-24_1140_репосты_в_каналах_и_тредах.md rename to Dev_Docs/Future_Features/medium/2026-05-24_1140_репосты_в_каналах_и_тредах.md index 14238fa..641ff28 100644 --- a/Dev_Docs/Future_Features/2026-05-24_1140_репосты_в_каналах_и_тредах.md +++ b/Dev_Docs/Future_Features/medium/2026-05-24_1140_репосты_в_каналах_и_тредах.md @@ -3,6 +3,12 @@ - Статус: `future` +- Горизонт: + `medium` + +- Ориентир: + 1-2 месяца + - Решение от 2026-05-24: Репосты временно убраны из активной разработки. Фича уже была частично реализована, но не доведена до финальной проверки. Чтобы она не мешала запуску проекта, пользовательский вход в репосты отключён в UI, а сервер больше не принимает новые `TEXT_REPOST` через `AddBlock`. diff --git a/Dev_Docs/Future_Features/medium/2026-05-25_1106_shine_balance_wallet.md b/Dev_Docs/Future_Features/medium/2026-05-25_1106_shine_balance_wallet.md new file mode 100644 index 0000000..6e35bca --- /dev/null +++ b/Dev_Docs/Future_Features/medium/2026-05-25_1106_shine_balance_wallet.md @@ -0,0 +1,62 @@ +# Кошелёк и пополнение баланса сияния + +- Горизонт: + `medium` +- Ориентир: + среднесрочно +- Статус: + `proposal` + +## Кратко + +Нужно добавить кошелёк для внутреннего баланса сияния и пополнение этого баланса через блокчейн-логику проекта. Задача связана с регистрацией пользователя и будущим учётом баланса. + +## Предполагаемый сценарий + +1. Пользователь регистрируется и получает/подключает нужные кошельки. +2. В интерфейсе появляется баланс сияния. +3. Пользователь открывает пополнение баланса сияния. +4. Система создаёт или принимает блокчейн-операцию пополнения. +5. После подтверждения баланса UI обновляет значение. + +## Что нужно продумать + +1. Что именно является единицей баланса сияния. +2. Где хранится состояние баланса: в существующем блокчейне SHiNE, Solana-модуле или комбинированно. +3. Какая операция отвечает за пополнение. +4. Нужно ли делать отдельную регистрацию кошелька сияния или использовать существующую регистрацию пользователя. +5. Как баланс восстанавливается после перезагрузки клиента. +6. Какие права нужны для пополнения и списания. +7. Нужна ли история операций баланса. + +## Вопросы перед реализацией + +1. Пополнение баланса сияния должно идти через основной блокчейн SHiNE или через Solana-программу. +2. Нужна ли конвертация из SOL/AR в сияние. +3. Кто может выпускать или начислять сияние. +4. Нужно ли поддерживать перевод сияния между пользователями. +5. Нужны ли лимиты, комиссии или статусы подтверждения. +6. Какой экран должен показывать баланс: регистрация, профиль, кошелёк или отдельная страница. +7. Нужно ли отображать неподтверждённый баланс отдельно от подтверждённого. + +## Важное ограничение + +Если для баланса сияния потребуется новый формат блокчейн-блока или изменение существующего формата, перед реализацией нужно отдельно предупредить пользователя и получить явное подтверждение на изменение формата блокчейна. + +Если потребуется новый серверный API или изменение существующих `op`, перед реализацией нужно отдельно предупредить пользователя и получить явное подтверждение на изменение API. + +## Документы, которые обновить при реализации + +- `Dev_Docs/Blockchain/`, если появятся или изменятся блоки баланса. +- `Dev_Docs/Blockchain/CHANGELOG.md`, если меняется блокчейн-формат. +- `Dev_Docs/API/`, если меняется серверный API. +- `Dev_Docs/Pending_Features/` - добавить файл ручной проверки после реализации. +- Документацию Solana-регистрации, если баланс будет связан с Solana-модулем. + +## Минимальная проверка в будущем + +1. Новый пользователь видит корректный начальный баланс. +2. Пополнение создаёт правильную операцию. +3. Баланс обновляется после подтверждения. +4. После перезагрузки UI баланс остаётся корректным. +5. Ошибочные или повторные операции не начисляют баланс дважды. diff --git a/Dev_Docs/Future_Features/near/2026-05-25_1106_channels_my_create_button.md b/Dev_Docs/Future_Features/near/2026-05-25_1106_channels_my_create_button.md new file mode 100644 index 0000000..7d88473 --- /dev/null +++ b/Dev_Docs/Future_Features/near/2026-05-25_1106_channels_my_create_button.md @@ -0,0 +1,67 @@ +# Кнопка создания канала только в разделе «Мои каналы» + +- Горизонт: + `near` +- Ориентир: + сегодня/завтра +- Статус: + `proposal` + +## Кратко + +Нужно поправить экран каналов: в общем списке должна быть простая надпись `Каналы` и переход к своим каналам, а кнопка создания канала должна появляться только в разделе `Мои каналы`. + +## Ожидаемый сценарий + +### Общий список + +1. Заголовок: `Каналы`. +2. Есть кнопка перехода в свои каналы: `Мои` или `Мои каналы`. +3. Кнопки создания канала в общем списке нет. + +### Раздел своих каналов + +1. Заголовок: `Мои каналы`. +2. Слева есть переход назад или кнопка `Ко всем каналам`. +3. Справа от заголовка или в правой части шапки есть маленькая кнопка `+` для создания канала. +4. Кнопка создания канала работает только здесь. + +## Что нужно сделать + +1. Найти компонент/страницу списка каналов в UI. +2. Разделить состояние общего списка и списка своих каналов. +3. Убрать кнопку создания канала из общего списка. +4. Добавить или оставить кнопку создания канала в `Мои каналы`. +5. Поправить заголовки: + - общий список: `Каналы`; + - свой список: `Мои каналы`. +6. Проверить расположение кнопок на мобильном и desktop-экране. +7. Убедиться, что существующее создание канала не ломается. + +## Вопросы перед реализацией + +1. Какой текст кнопки перехода лучше: `Мои`, `Мои каналы` или иконка с подписью. +2. Нужна ли отдельная стрелка назад, если уже есть кнопка `Ко всем каналам`. +3. Кнопка `+` должна быть иконкой без текста или `Создать канал`. +4. Нужно ли сохранять выбранный режим после перезагрузки страницы. + +## Риски и ограничения + +- Нужно проверить, не завязаны ли текущие обработчики создания канала на общий экран. +- На узких экранах заголовок, кнопка назад и `+` могут конфликтовать по ширине. +- Если есть роутинг по query/state, важно не сломать прямые переходы. + +## Документы, которые обновить при реализации + +- `Dev_Docs/Pending_Features/` - добавить файл ручной проверки после реализации. +- UI-документацию, если в проекте есть отдельное описание экранов каналов. + +## Минимальная проверка + +1. В общем списке виден заголовок `Каналы`. +2. В общем списке нет кнопки создания канала. +3. Переход в `Мои каналы` работает. +4. В `Мои каналы` видна кнопка создания канала. +5. Создание канала из `Мои каналы` работает. +6. Возврат ко всем каналам работает. +7. На мобильном экране шапка не ломается. diff --git a/Dev_Docs/Future_Features/near/2026-05-25_1106_telegram_agent_players.md b/Dev_Docs/Future_Features/near/2026-05-25_1106_telegram_agent_players.md new file mode 100644 index 0000000..2022dc0 --- /dev/null +++ b/Dev_Docs/Future_Features/near/2026-05-25_1106_telegram_agent_players.md @@ -0,0 +1,94 @@ +# Telegram-агент для разрешённых игроков + +- Горизонт: + `near` +- Ориентир: + сегодня/завтра +- Статус: + `proposal` + +## Кратко + +Нужно расширить `SHiNE-agent-bot-coder`, чтобы агент мог принимать личные сообщения от заранее разрешённых пользователей, вести по каждому отдельную рабочую папку и историю, помогать им с обсуждениями/документами без изменения кода, а краткий результат публиковать в общий канал. + +## Пользовательский сценарий + +1. Разрешённый пользователь пишет агенту в личные сообщения текстом или голосом. +2. Голосовое сообщение распознаётся так же, как сейчас распознаются voice/audio-задачи. +3. Сервис определяет пользователя по разрешённому списку логинов. +4. Для пользователя используется отдельная папка в `Players/`. +5. Codex запускается с системным контекстом: от имени какого человека он работает, где лежит его папка, какие у него локальные инструкции. +6. Агент может читать код и документацию проекта, но писать должен только в папку этого пользователя, если нет отдельного согласования на изменение общего проекта. +7. После ответа пользователю агент отправляет в общий канал короткую сводку двумя сообщениями или двумя блоками: вопрос пользователя и полученный ответ. +8. Команда `/new` или `New` сбрасывает только сессию этого пользователя. + +## Предлагаемая структура + +- `Players/` + - `Ivan/` + - `AGENTS.md` + - `history/` + - `files/` + - `Sergey/` + - `AGENTS.md` + - `history/` + - `files/` + - `Milana/` + - `AGENTS.md` + - `history/` + - `files/` + +Имена папок можно уточнить после получения точных Telegram-логинов. + +## Что нужно сделать + +1. Добавить конфигурацию разрешённых Telegram-пользователей. +2. Описать соответствие `telegram username -> имя игрока -> папка`. +3. Создавать или использовать отдельную историю диалога для каждого игрока. +4. Поддержать личные сообщения от разрешённых пользователей. +5. Запретить постановку задач от неизвестных пользователей. +6. Для групп/каналов оставить текущую логику: команды Айдара имеют приоритет. +7. При запуске Codex для игрока добавлять отдельный системный контекст: + - имя пользователя; + - путь к его папке; + - правило записи только в эту папку; + - путь к персональному `AGENTS.md`. +8. После ответа игроку отправлять краткую сводку в общий канал. +9. Поддержать `/new`/`New` как сброс только персональной сессии игрока. +10. Добавить защиту от случайного изменения общего кода в режиме игрока. + +## Вопросы перед реализацией + +1. Точные Telegram-логины Ивана, Сергея и Миланы. +2. Какой общий канал использовать для сводок: текущий `@shine_writing` или отдельный чат. +3. Нужно ли отправлять в общий канал полный текст вопроса/ответа или краткую выжимку. +4. Нужно ли пересылать вложения игроков в общий канал или только текстовые сводки. +5. Разрешить ли игрокам читать все документы проекта, включая технические заметки деплоя. +6. Что делать, если пользователь просит изменить код: отказать, создать предложение в своей папке или просить подтверждение Айдара. +7. Нужны ли русские имена папок (`Иван`, `Сергей`, `Милана`) или ASCII-имена (`Ivan`, `Sergey`, `Milana`). +8. Нужно ли хранить истории игроков в общей папке сервиса или внутри `Players//history/`. + +## Риски и ограничения + +- Нужно аккуратно разделить режим Айдара и режим игрока, чтобы игроки не могли случайно запустить изменение общего кода. +- Нужно не смешать истории разных пользователей. +- Нужно ограничить публикацию в общий канал, чтобы не утекали личные или слишком длинные ответы. +- Нужна проверка Telegram-идентификации: username может меняться, поэтому желательно хранить и `user_id`. + +## Документы, которые обновить при реализации + +- `SHiNE-agent-bot-coder/AGENTS.md` +- `SHiNE-agent-bot-coder/AGENT.md` +- `SHiNE-agent-bot-coder/README.md` +- `Dev_Docs/deploy/agent-bot-coder-local-systemd.md`, если появятся новые переменные окружения или настройки сервиса. + +## Минимальная проверка + +1. Айдар по-прежнему может ставить задачи из `@shine_writing`. +2. Неизвестный пользователь не ставит задачу в очередь. +3. Разрешённый игрок пишет личное текстовое сообщение и получает ответ. +4. Разрешённый игрок отправляет voice, оно распознаётся и обрабатывается. +5. История одного игрока не попадает в историю другого. +6. `/new` сбрасывает только историю текущего игрока. +7. Сводка вопрос/ответ появляется в общем канале. +8. В режиме игрока агент не пишет за пределы `Players//` без отдельного подтверждения. diff --git a/Dev_Docs/Future_Features/near/2026-05-25_1106_wallet_topup_solana_arweave.md b/Dev_Docs/Future_Features/near/2026-05-25_1106_wallet_topup_solana_arweave.md new file mode 100644 index 0000000..c4c06a9 --- /dev/null +++ b/Dev_Docs/Future_Features/near/2026-05-25_1106_wallet_topup_solana_arweave.md @@ -0,0 +1,71 @@ +# Пополнение Solana и Arweave через внешний сервис покупки + +- Горизонт: + `near` +- Ориентир: + сегодня/завтра +- Статус: + `proposal` + +## Кратко + +Нужно добавить удобное пополнение кошельков на экране регистрации/кошелька: для Solana и Arweave дать отдельные действия `Пополнить`, которые ведут на международный сервис покупки криптовалюты с карты и помогают пользователю скопировать адрес кошелька. + +## Пользовательский сценарий + +1. Пользователь видит адрес кошелька Solana или Arweave. +2. Нажимает `Пополнить`. +3. Открывается промежуточное окно с инструкцией: + - сейчас пользователь перейдёт на страницу покупки/пополнения; + - нужно указать или проверить адрес кошелька; + - после оплаты нужно закрыть внешнюю страницу и вернуться назад; + - Solana обычно приходит быстро, ориентир 10-15 секунд после подтверждения сети; + - Arweave может идти дольше, точное время нужно уточнить по выбранному сервису. +4. В окне есть кнопки: + - `Скопировать адрес и перейти`; + - `Перейти без копирования`. +5. Для Solana и Arweave используются разные окна/инструкции и, возможно, разные внешние ссылки. + +## Что нужно сделать + +1. Найти текущий экран, где показываются кошельки при регистрации и пополнении. +2. Найти текущую ссылку покупки Arweave, если она уже есть в UI. +3. Выбрать международный сервис покупки Solana с карты, не российский. +4. Проверить, поддерживает ли сервис deep link с предзаполненным адресом кошелька. +5. Если deep link невозможен, реализовать промежуточное окно с копированием адреса. +6. Добавить отдельные действия для Solana и Arweave. +7. Сделать текст инструкции коротким и понятным. +8. Проверить, что адрес копируется в буфер обмена в браузере. +9. Проверить мобильный сценарий и desktop-сценарий. + +## Вопросы перед реализацией + +1. Какой сервис покупки Solana использовать: тот же провайдер, что для Arweave, или другой международный on-ramp. +2. Нужно ли разрешать покупку только SOL или также USDC/SPL-токены на Solana. +3. Где именно показывать кнопку `Пополнить`: только регистрация, настройки кошелька или оба места. +4. Нужно ли показывать предупреждение о комиссиях и стороннем сервисе. +5. Нужно ли открывать внешнюю страницу в новой вкладке или в текущем окне. +6. Нужно ли логировать факт нажатия `Пополнить` на сервере. +7. Какой точный текст использовать для времени прихода Arweave. + +## Риски и ограничения + +- On-ramp-сервисы меняют ссылки и параметры, поэтому deep link нужно проверять перед реализацией. +- Clipboard API может требовать HTTPS и пользовательский жест. +- Нельзя обещать точное время поступления средств: лучше писать ориентир и зависимость от сети/провайдера. +- Внешний сервис может быть недоступен в отдельных странах или для отдельных карт. + +## Документы, которые обновить при реализации + +- Документацию UI/кошельков, если такая есть. +- `Dev_Docs/Pending_Features/` - добавить файл ручной проверки после реализации. +- `Dev_Docs/API/`, только если появится новый серверный API или логирование. + +## Минимальная проверка + +1. На Solana-кошельке открывается правильное окно пополнения. +2. Кнопка `Скопировать адрес и перейти` копирует Solana-адрес и открывает внешний сервис. +3. Кнопка `Перейти без копирования` открывает внешний сервис без копирования. +4. Аналогичный сценарий работает для Arweave. +5. На мобильном экране текст и кнопки не перекрываются. +6. Возврат назад в приложение не ломает состояние регистрации/кошелька. diff --git a/Dev_Docs/Pending_Features/2026-05-24_2035_solana-init-registracii.md b/Dev_Docs/Pending_Features/2026-05-24_2035_solana-init-registracii.md new file mode 100644 index 0000000..8c9e868 --- /dev/null +++ b/Dev_Docs/Pending_Features/2026-05-24_2035_solana-init-registracii.md @@ -0,0 +1,26 @@ +# Solana: init регистрации + деплой обязательных программ + +- дата: 2026-05-24 20:35 (Europe/Moscow) +- статус: `pending` + +## Кратко + +Добавлена dev-страница в UI для вызова `init_users_economy_config` программы `shine_users` через подключённый кошелёк Phantom. +Задеплоены и зафиксированы адреса двух обязательных программ регистрации: `shine_users` и `shine_login_guard`. + +## Что проверять вручную + +1. Открыть UI и перейти в `Настройки разработчика`. +2. Нажать `Solana: init регистрации`. +3. Подключить Phantom devnet-кошелёк. +4. Выполнить `init_users_economy_config`. +5. Проверить отображение статуса и хэша транзакции. +6. Повторно нажать init и убедиться, что корректно показывается "уже инициализировано". +7. Выполнить тестовую регистрацию пользователя и убедиться, что CPI-вызов `shine_login_guard` не падает. + +## Ожидаемый результат + +- Первая транзакция выполняется успешно (если PDA ещё не создан). +- Вторая попытка возвращает ожидаемую ошибку о повторной инициализации. +- UI не падает, статус понятный, Program ID отображается корректно. +- Регистрация пользователя проходит с подключённым `shine_login_guard`. diff --git a/Dev_Docs/Pending_Features/2026-05-25_1545_otchet_private_zaprosov_v_gruppu.md b/Dev_Docs/Pending_Features/2026-05-25_1545_otchet_private_zaprosov_v_gruppu.md new file mode 100644 index 0000000..89fff13 --- /dev/null +++ b/Dev_Docs/Pending_Features/2026-05-25_1545_otchet_private_zaprosov_v_gruppu.md @@ -0,0 +1,26 @@ +# Отчёт private-запросов агента в группу + +## Что сделано + +После успешной обработки задачи из личного чата Айдара Telegram-бот агента отправляет итоговую копию в группу `@shine_writing`: + +- первым сообщением исходный запрос; +- вторым сообщением, reply на первое, финальный ответ Codex. + +Промежуточные статусы выполнения в группу не дублируются. + +## Что проверять + +1. Отправить боту личный текстовый запрос. +2. Дождаться полного ответа в личном чате. +3. Проверить, что в `@shine_writing` появилось сообщение с запросом. +4. Проверить, что итоговый ответ опубликован reply на это сообщение. +5. Отправить личный voice-запрос и проверить, что в отчёте есть распознанный текст. + +## Ожидаемый результат + +Личный чат работает как раньше, а группа получает только итоговую пару сообщений по завершённой задаче. + +## Статус + +pending diff --git a/Dev_Docs/Pending_Features/2026-05-25_1556_voice_otchet_s_audio.md b/Dev_Docs/Pending_Features/2026-05-25_1556_voice_otchet_s_audio.md new file mode 100644 index 0000000..9c7d627 --- /dev/null +++ b/Dev_Docs/Pending_Features/2026-05-25_1556_voice_otchet_s_audio.md @@ -0,0 +1,23 @@ +# Отчёт voice/audio-запросов с исходным файлом + +## Краткое описание + +Публичный отчёт по приватным voice/audio-запросам агента должен отправлять исходный Telegram voice/audio-файл с подписью, где указан распознанный текст. `file_id` не должен показываться пользователям в тексте отчёта. + +## Что проверить + +1. Отправить боту приватный voice-запрос от Айдара. +2. Дождаться обработки Codex. +3. Проверить группу/канал публичных отчётов. +4. Повторить сценарий для audio-файла, если он используется. + +## Ожидаемый результат + +- В публичном отчёте появляется исходное голосовое/audio-сообщение. +- В подписи к нему есть распознанный текст. +- В отчёте нет строки `Голосовой file_id` и самого `file_id`. +- Итоговый ответ Codex отправляется ответом на сообщение с исходным файлом. + +## Статус + +pending diff --git a/Dev_Docs/Pending_Features/2026-05-25_2057_voice_timeout_i_oshibki.md b/Dev_Docs/Pending_Features/2026-05-25_2057_voice_timeout_i_oshibki.md new file mode 100644 index 0000000..6f68ec0 --- /dev/null +++ b/Dev_Docs/Pending_Features/2026-05-25_2057_voice_timeout_i_oshibki.md @@ -0,0 +1,19 @@ +# Улучшенная обработка длинных voice/audio + +## Что сделано +- Увеличены и вынесены в `.env` тайм-ауты скачивания Telegram-файла и OpenAI-распознавания. +- Добавлены подробные логи стадий распознавания: старт, скачивание, размер файла, завершение, причина ошибки. +- Ошибки voice/audio теперь показываются пользователю как ошибка распознавания с понятной причиной. + +## Как проверять +- Отправить короткое голосовое сообщение и убедиться, что оно распознаётся и передаётся в Codex. +- Отправить длинное голосовое сообщение и убедиться, что сервис не падает на прежнем коротком тайм-ауте. +- Смоделировать ошибку распознавания или временно указать неверный OpenAI-ключ и проверить текст ошибки в Telegram. + +## Ожидаемый результат +- При успешном распознавании пользователь видит распознанный текст и задача уходит в Codex. +- При ошибке пользователь видит, что не удалось именно распознать voice/audio, и получает конкретную причину. +- В логах сервиса видны стадия и техническая причина сбоя. + +## Статус +pending diff --git a/Dev_Docs/Solana/user_pda/README.md b/Dev_Docs/Solana/user_pda/README.md index 299b098..036c130 100644 --- a/Dev_Docs/Solana/user_pda/README.md +++ b/Dev_Docs/Solana/user_pda/README.md @@ -51,7 +51,7 @@ | N | Поле | Тип | Размер | Правило | |---|------|-----|--------|---------| | 1 | `magic` | bytes | 5 | Всегда `SHiNE`. | -| 2 | `format_major` | `u8` | 1 | Для нового формата: `2`. | +| 2 | `format_major` | `u8` | 1 | Для первого формата: `1`. | | 3 | `format_minor` | `u8` | 1 | Для первой версии нового формата: `0`. | | 4 | `record_len` | `u16` | 2 | Длина полезной записи от `magic` до `signature` включительно, без padding. | | 5 | `created_at_ms` | `u64` | 8 | Время создания записи, Unix time в миллисекундах. Не меняется. | @@ -63,7 +63,7 @@ После первых 9 полей идет набор типизированных блоков: ```text -UserPdaRecordV2 +UserPdaRecordV1 - fixed_header: поля 1..9 - blocks_count: u8 - blocks: TypedBlock[blocks_count] @@ -89,7 +89,7 @@ UserPdaRecordV2 Правила: -- неизвестный `block_type` в `format_major = 2` считается ошибкой; +- неизвестный `block_type` в `format_major = 1` считается ошибкой; - обязательные блоки: `RootKeyBlock`, `DeviceKeyBlock`, `BlockchainRegistryBlock`; - необязательные блоки: `ServerProfileBlock`, `AccessServersBlock`, `TrustedStateBlock`; - каждый обязательный блок должен встречаться ровно один раз; diff --git a/Dev_Docs/Solana_Architecture/README.md b/Dev_Docs/Solana_Architecture/README.md new file mode 100644 index 0000000..2252f7b --- /dev/null +++ b/Dev_Docs/Solana_Architecture/README.md @@ -0,0 +1,166 @@ +# Архитектура Solana-программ SHiNE + +Документ описывает рабочую архитектуру Solana-части SHiNE: три Anchor-программы, DAO, ключи управления, PDA-счета и движение денег. + +Это архитектурная справка. Она не меняет код, формат PDA-записи пользователя, серверный API или формат блокчейна SHiNE. + +Статус: актуализировано по коду `shine-solana/shine/programs/*` на 2026-05-25. + +Связанные документы: + +- `Dev_Docs/Инициализация_Solana_регистрации/README.md` — single source of truth по деплою и первичной инициализации регистрации пользователей. +- `shine-solana/shine/doc/SHiNE-user-format-v.1.0.md` — точный формат `user_pda` для `shine_users`. +- `shine-solana/shine/doc/FUNDS_FLOW.md` — короткая справка по денежным потокам внутри Solana-модуля. + +## Кратко + +В Solana-модуле сейчас три основные программы: + +1. `shine_login_guard` — проверяет логин и возвращает класс логина: обычный, premium или trademark. +2. `shine_users` — создает и обновляет пользовательскую PDA-запись, проверяет подписи и берет оплату за регистрацию/увеличение лимита. +3. `shine_payments` — принимает входящий поток средств в `inflow_vault`, ведет очереди тикетов, позволяет DAO выдавать лимиты менеджерам и выполняет выплаты. + +DAO в текущем виде не является отдельной Anchor-программой SHiNE внутри `programs/`. Это управляющая модель поверх кошельков, governance-скриптов и authority-адресов. Для проектирования ее удобно считать отдельным управляющим блоком: DAO голосует, назначает управляющие ключи, управляет казной и вызывает защищенные методы второй и третьей программ. + +## Общая схема + +Редактируемая Mermaid-схема находится в [schemes/architecture.mmd](schemes/architecture.mmd). + +Картинки: + +- [schemes/architecture.svg](schemes/architecture.svg) +- [schemes/architecture.png](schemes/architecture.png) + +## Программы и функции + +| Блок | Папка/имя | Текущие функции из кода | Основной смысл | +| --- | --- | --- | --- | +| 1 | `shine_login_guard` | `classify_login` | Проверка логина перед регистрацией. | +| 2 | `shine_users` | `init_users_economy_config`, `update_users_economy_config`, `create_user_pda`, `update_user_pda` | Регистрация пользователя, обновление записи, экономика лимита. | +| 3 | `shine_payments` | `init`, `update_coef_limit`, `grant_manager_limits`, `buy_ticket`, `buy_ticket_usd`, `buy_ticket_sol`, `manager_add_ticket`, `step_payout`, `change_ticket_recipient` | Vault, билеты, очереди, выплаты, DAO-настройки, лимиты менеджеров. | +| DAO | governance/authority | Вызовы через governance и управляющие ключи | Управление правами, казной, настройками и будущими обновлениями программ. | + +## Актуальные program id + +Актуальные адреса заданы одновременно в `Anchor.toml`, `declare_id!` программ и `programs/common/src/deploy_config.rs`: + +| Программа | Program ID | +| --- | --- | +| `shine_login_guard` | `3xkopA7cXagxzMFrKdv3NCBfV6BKiRJCk69kr27M2sRo` | +| `shine_users` | `FZS1YctoeEhCkZ5VTjsysUFAXR8CqxYztcLboXcg2Rpm` | +| `shine_payments` | `m48pWRGWrMj3TEHjuU4zsp5Gju4e7ZaPovk8RcVt7kR` | + +Если эти адреса меняются, нужно синхронно обновить: + +1. `shine-solana/shine/Anchor.toml` +2. `declare_id!` в `programs/*/src/lib.rs` +3. `programs/common/src/deploy_config.rs` +4. UI/серверные константы, перечисленные в `Dev_Docs/Инициализация_Solana_регистрации/README.md` + +## Ключи и authority + +Для удобного понимания на старте можно считать, что есть четыре группы ключей: + +1. `key_1` / authority программы `shine_login_guard`. + - Сейчас программа только классифицирует логин. + - На первом этапе ее можно оставить под отдельным ключом. + - В будущем право обновления можно передать DAO. + +2. `key_2` / authority программы `shine_users`. + - Отвечает за деплой/upgrade второй программы. + - Защищенное обновление economy-конфига в коде уже проверяет `DAO_AUTHORITY`. + - В целевой модели upgrade-authority второй программы нужно передать DAO. + +3. `key_3` / authority программы `shine_payments`. + - Отвечает за деплой/upgrade третьей программы. + - Защищенные методы `update_coef_limit` и `grant_manager_limits` проверяют `dao_wallet` из `ConfigState`. + - В целевой модели upgrade-authority третьей программы нужно передать DAO. + +4. DAO-ключи. + - Это управляющие кошельки/токены/realm governance. + - DAO может добавлять и отзывать управляющие ключи по голосованию. + - DAO-казна получает деньги от покупки тикетов и DAO-часть выплат из `inflow_vault`. + +Адреса program id сейчас берутся из `programs/common/src/deploy_config.rs`. Для production/devnet можно подбирать vanity-адреса с понятным началом вроде `SHi...`, но это отдельная операция генерации ключей и деплоя. + +## Счета и PDA + +Постоянные PDA и счета: + +1. `shine_users` + - `user_pda` — пользовательская запись по seed `login=`, создается для каждого логина. + - `users_economy_config_pda` — общие параметры экономики регистрации и лимита. + +2. `shine_payments` + - `config_pda` — хранит `dao_wallet` и адрес `inflow_vault`. + - `coef_limit_pda` — хранит коэффициент выплат, лимит очереди и награду вызывающему `step_payout`. + - `queues_pda` — агрегаты очередей выплат. + - `inflow_vault_pda` — PDA-вольт, куда `shine_users` переводит оплату регистрации и увеличения лимита. + - `ticket_pda` — отдельная PDA-запись тикета на каждую покупку/менеджерскую выдачу. + - `manager_allowance_pda` — PDA лимитов конкретного менеджера. + +3. DAO + - `dao_wallet` / treasury — казна DAO. + - governance-аккаунты DAO — realm, governance, proposal/vote records и связанные аккаунты SPL Governance, если используется эта модель. + +## Правило разделения с основным сервером + +Solana-модуль лежит в основном репозитории как отдельная папка `shine-solana/shine/`, но не подключается автоматически к сборке или деплою основного сервера SHiNE. Команды `deployServer` и `deployUI` не должны деплоить Anchor-программы. Solana build/deploy выполняется отдельно из папки `shine-solana/shine/` по локальным правилам модуля. + +## Движение денег + +Основные потоки: + +1. Регистрация пользователя через `shine_users::create_user_pda`. + - Платит `signer`. + - Деньги идут в `shine_payments::inflow_vault_pda`. + - Сумма состоит из регистрационной комиссии и оплаты дополнительного лимита. + +2. Увеличение лимита через `shine_users::update_user_pda`. + - Платит `signer`. + - Деньги идут в тот же `inflow_vault_pda`. + - Сумма равна оплате дополнительного лимита. + +3. Покупка тикета через `shine_payments::buy_ticket*`. + - Платит покупатель. + - Деньги сразу идут в `dao_wallet`. + - Одновременно создается тикет на выплату. + +4. Выплата через `shine_payments::step_payout`. + - Вызвать может любой подписант. + - Деньги берутся из `inflow_vault_pda`. + - Часть идет получателю тикета. + - Часть идет в `dao_wallet`. + - Небольшая награда идет вызвавшему шаг выплат. + - Если очереди пустые, весь доступный остаток `inflow_vault_pda` переводится в DAO. + +## Передача прав DAO + +Минимальная целевая модель: + +1. `shine_login_guard` + - Пока оставить на отдельном ключе `key_1`. + - Передачу DAO сделать позже, когда логика premium/trademark стабилизируется. + +2. `shine_users` + - Economy-настройки уже должны обновляться DAO-authority. + - Upgrade-authority программы после проверки можно передать DAO. + +3. `shine_payments` + - DAO уже управляет настройками выплат и лимитами менеджеров через `dao_wallet`. + - Upgrade-authority программы после проверки можно передать DAO. + +4. DAO + - Управляет казной. + - Принимает решения голосованием. + - Добавляет/отзывает управляющие ключи. + - Вызывает защищенные методы второй и третьей программ. + - В будущем может принять управление первой программой. + +## Детальные файлы + +- [details/shine_login_guard.md](details/shine_login_guard.md) +- [details/shine_users.md](details/shine_users.md) +- [details/shine_payments.md](details/shine_payments.md) +- [details/shine_dao.md](details/shine_dao.md) +- [details/accounts_and_money_flow.md](details/accounts_and_money_flow.md) diff --git a/Dev_Docs/Solana_Architecture/details/accounts_and_money_flow.md b/Dev_Docs/Solana_Architecture/details/accounts_and_money_flow.md new file mode 100644 index 0000000..1f97c43 --- /dev/null +++ b/Dev_Docs/Solana_Architecture/details/accounts_and_money_flow.md @@ -0,0 +1,110 @@ +# Счета, ключи и движение денег + +## Кратко + +В архитектуре есть три типа объектов: + +1. Ключи программ и DAO. +2. PDA-счета состояния. +3. Денежные счета, через которые проходят SOL/lamports. + +## Ключи + +Минимальный набор для понимания: + +1. `key_1` — deploy/upgrade authority `shine_login_guard`. +2. `key_2` — deploy/upgrade authority `shine_users`. +3. `key_3` — deploy/upgrade authority `shine_payments`. +4. `DAO_AUTHORITY` — адрес, который имеет право менять защищенные настройки. +5. `DAO_TREASURY_WALLET` / `dao_wallet` — казна DAO. +6. `manager_wallet` — кошелек менеджера, которому DAO выдает лимиты на создание тикетов. +7. `user root_key` — корневой ключ пользователя для подписи пользовательской записи. +8. `user device_key` — ключ устройства пользователя. +9. `server_key` — ключ сервера пользователя, если пользователь является сервером. + +Текущие адреса из `programs/common/src/deploy_config.rs`: + +| Роль | Адрес | +| --- | --- | +| `SHINE_LOGIN_GUARD_PROGRAM_ID` | `3xkopA7cXagxzMFrKdv3NCBfV6BKiRJCk69kr27M2sRo` | +| `SHINE_USERS_PROGRAM_ID` | `FZS1YctoeEhCkZ5VTjsysUFAXR8CqxYztcLboXcg2Rpm` | +| `SHINE_PAYMENTS_PROGRAM_ID` | `m48pWRGWrMj3TEHjuU4zsp5Gju4e7ZaPovk8RcVt7kR` | +| `DAO_AUTHORITY` | `FUc28vNixp7F3nnkpGVt6nuJbgvJ4429v4B5wS52Df6P` | +| `DAO_TREASURY_WALLET` | `FUc28vNixp7F3nnkpGVt6nuJbgvJ4429v4B5wS52Df6P` | + +## Постоянные PDA + +`shine_users`: + +- `user_pda` — создается для каждого логина, seed `login=` + normalized login. +- `users_economy_config_pda` — один PDA с экономикой регистрации, seed `shine_users_economy_config`. + +`shine_payments`: + +- `config_pda` — один PDA конфига, seed `shine_payments_config`. +- `coef_limit_pda` — один PDA коэффициента/лимита/награды, seed `shine_payments_coef_limit`. +- `queues_pda` — один PDA агрегатов очередей, seed `shine_payments_queues`. +- `inflow_vault_pda` — один PDA-вольт входящих средств, seed `shine_payments_inflow_vault`. +- `ticket_pda` — много PDA, по одному на тикет, seed `shine_payments_q1_ticket` или `shine_payments_q2_ticket` + индекс. +- `manager_allowance_pda` — много PDA, по одному на менеджера, seed `shine_p_manager_allow` + адрес менеджера. + +## Денежные потоки + +### Регистрация + +```text +user signer -> shine_users::create_user_pda -> shine_payments::inflow_vault_pda +``` + +Состав платежа: + +- регистрационная комиссия; +- оплата `additional_limit`. + +### Увеличение лимита + +```text +user signer -> shine_users::update_user_pda -> shine_payments::inflow_vault_pda +``` + +Состав платежа: + +- только оплата `additional_limit`. + +### Покупка тикета + +```text +buyer signer -> shine_payments::buy_ticket* -> dao_wallet +``` + +При этом создается `ticket_pda`, но деньги в `inflow_vault_pda` на этом шаге не идут. + +### Выплата + +```text +shine_payments::inflow_vault_pda -> ticket_recipient_wallet +shine_payments::inflow_vault_pda -> dao_wallet +shine_payments::inflow_vault_pda -> step_payout caller +``` + +Если очереди пустые: + +```text +shine_payments::inflow_vault_pda -> dao_wallet +``` + +## Что нужно создать на старте + +Минимально: + +1. Три program id для `shine_login_guard`, `shine_users`, `shine_payments`. +2. Три upgrade-authority ключа или один временный deploy-ключ с четким планом передачи прав. +3. DAO authority/treasury. +4. `users_economy_config_pda`. +5. `shine_payments` PDA: `config_pda`, `coef_limit_pda`, `queues_pda`, `inflow_vault_pda`. + +Динамически будут создаваться: + +- `user_pda` на каждого пользователя; +- `ticket_pda` на каждый тикет; +- `manager_allowance_pda` на каждого менеджера. diff --git a/Dev_Docs/Solana_Architecture/details/shine_dao.md b/Dev_Docs/Solana_Architecture/details/shine_dao.md new file mode 100644 index 0000000..ce8ea98 --- /dev/null +++ b/Dev_Docs/Solana_Architecture/details/shine_dao.md @@ -0,0 +1,74 @@ +# SHiNE DAO + +## Кратко + +DAO — управляющий слой Solana-части SHiNE. В текущем коде это не отдельная Anchor-программа в `programs/`, а модель управления через DAO-кошелек, DAO-authority, governance-скрипты и будущую передачу upgrade-authority программ. + +## Что DAO должно уметь + +1. Управлять казной. + - Принимать средства на `dao_wallet`. + - Выплачивать средства со счета DAO по решениям голосования. + +2. Управлять настройками `shine_users`. + - Обновлять регистрационную комиссию. + - Обновлять цену шага лимита. + - Обновлять стартовый бонус лимита. + +3. Управлять настройками `shine_payments`. + - Обновлять коэффициент выплат. + - Обновлять лимит очереди. + - Обновлять награду за вызов `step_payout`. + +4. Управлять менеджерами. + - Выдавать менеджеру лимит на добавление тикетов. + - Отдельно учитывать лимиты Q1 и Q2. + +5. Управлять правами программ. + - Принять upgrade-authority `shine_users`. + - Принять upgrade-authority `shine_payments`. + - Позже принять upgrade-authority `shine_login_guard`, если это потребуется. + +6. Управлять ключами DAO. + - Добавлять управляющие ключи. + - Отзывать или сжигать управляющие ключи. + - Делать это через голосование, а не вручную одним админом. + +7. Фиксировать решения. + - Делать заявления/решения через governance-механику. + - Привязывать важные изменения к proposal/vote/execute. + +## Текущие адреса управления + +В общем deploy-конфиге сейчас есть два важных адреса: + +- `DAO_AUTHORITY` — используется `shine_users` для проверки права менять economy-конфиг. +- `DAO_TREASURY_WALLET` — используется `shine_payments` как `dao_wallet`. + +Сейчас они могут совпадать. В целевой DAO-модели их лучше рассматривать как разные роли: + +- authority/governance signer — кто имеет право исполнять управленческие инструкции; +- treasury wallet — счет, куда приходят деньги DAO. + +## Передача прав + +Рекомендуемый порядок: + +1. Сначала стабилизировать и проверить `shine_users` и `shine_payments`. +2. Передать DAO право обновлять настройки, если оно еще не передано. +3. Передать DAO upgrade-authority второй и третьей программ. +4. Оставить `shine_login_guard` на отдельном ключе до стабилизации словарей и правил логинов. +5. После стабилизации решить отдельным голосованием, передавать ли первую программу DAO. + +## Важное разделение + +Есть два разных типа прав: + +1. Право вызвать защищенную функцию программы. + - Например, `update_coef_limit` или `grant_manager_limits`. + - Проверяется внутри программы по `dao_wallet` или `DAO_AUTHORITY`. + +2. Право обновить саму программу. + - Это upgrade-authority Solana ProgramData. + - Оно передается отдельной Solana-командой/DAO-транзакцией и не равно обычному PDA-счету. + diff --git a/Dev_Docs/Solana_Architecture/details/shine_login_guard.md b/Dev_Docs/Solana_Architecture/details/shine_login_guard.md new file mode 100644 index 0000000..aa76f6a --- /dev/null +++ b/Dev_Docs/Solana_Architecture/details/shine_login_guard.md @@ -0,0 +1,58 @@ +# `shine_login_guard` + +## Кратко + +`shine_login_guard` — первая программа Solana-модуля SHiNE. Она проверяет логин перед регистрацией пользователя и возвращает класс логина. + +Папка программы: `shine-solana/shine/programs/shine_login_guard/`. + +## Текущая функция + +1. `classify_login(login: String)` + - Нормализует логин. + - Проверяет длину и допустимые символы. + - Сравнивает части логина со словарями premium/trademark. + - Возвращает результат через `set_return_data`. + +Классы результата: + +- `0` — обычный логин, регистрацию можно продолжать. +- `1` — premium-логин. +- `2` — trademark-логин, нужна отдельная проверка/разрешение. + +## Правила нормализации и классификации + +Текущая логика из `programs/shine_login_guard/src/lib.rs`: + +- пустой логин или логин длиннее 20 символов получает класс `premium`; +- `_` при нормализации удаляется; +- допустимы только ASCII-буквы и цифры, остальные символы дают класс `premium`; +- после удаления `_` результат приводится к нижнему регистру; +- логины длиной 7 символов или меньше считаются `premium`; +- логин разбивается максимум на 3 словарных фрагмента; +- если среди найденных фрагментов есть trademark-слово, результат `trademark`; +- если найдены только premium-слова, результат `premium`; +- если разбиение по словарям не найдено, результат `free`. + +Словари собираются на этапе build из файлов: + +- `programs/shine_login_guard/src/dictionaries/premium/*.txt` +- `programs/shine_login_guard/src/dictionaries/trademarks/*.txt` + +## Роль в общей схеме + +`shine_users::create_user_pda` вызывает `shine_login_guard` через CPI и продолжает регистрацию только если логин получил класс `0`. + +## Ключи и управление + +На старте удобно считать, что у программы есть отдельный управляющий ключ `key_1`. + +Текущая рекомендация: + +- пока оставить `shine_login_guard` под отдельным ключом; +- не передавать ее DAO до стабилизации правил premium/trademark; +- позже можно передать upgrade-authority DAO, чтобы изменения словарей и правил проходили через голосование. + +## Счета + +Собственных постоянных PDA-счетов у программы сейчас нет. Для проверки нужен только подписант транзакции в `ClassifyLogin`. diff --git a/Dev_Docs/Solana_Architecture/details/shine_payments.md b/Dev_Docs/Solana_Architecture/details/shine_payments.md new file mode 100644 index 0000000..92d9da9 --- /dev/null +++ b/Dev_Docs/Solana_Architecture/details/shine_payments.md @@ -0,0 +1,173 @@ +# `shine_payments` + +## Кратко + +`shine_payments` — третья программа Solana-модуля SHiNE. Она отвечает за vault входящих средств, DAO-казну, покупку тикетов, менеджерские лимиты, очереди выплат и пошаговое исполнение выплат. + +Папка программы: `shine-solana/shine/programs/shine_payments/`. + +## Текущие функции + +1. `init` + - Создает основные PDA: `config_pda`, `coef_limit_pda`, `queues_pda`, `inflow_vault_pda`. + - Записывает `dao_wallet` и стартовые параметры выплат. + +2. `update_coef_limit` + - Обновляет коэффициент выплаты, лимит очереди и награду вызвавшему `step_payout`. + - Требует подпись DAO-кошелька из `ConfigState`. + +3. `grant_manager_limits` + - DAO выдает менеджеру лимиты на создание тикетов в очередях Q1/Q2. + - Создает или обновляет `manager_allowance_pda`. + +4. `buy_ticket` + - Покупка тикета с суммой в lamports, пересчетом через Pyth SOL/USD. + +5. `buy_ticket_usd` + - Покупка тикета от USD-центов с защитой по максимальному платежу в lamports. + +6. `buy_ticket_sol` + - Покупка тикета в lamports с проверкой минимального ожидаемого USD-эквивалента. + +7. `manager_add_ticket` + - Менеджер создает тикет за счет выданного ему DAO-лимита. + +8. `step_payout` + - Любой подписант может вызвать шаг выплат. + - Программа выплачивает следующий тикет, DAO-часть и награду вызывающему. + +9. `change_ticket_recipient` + - Текущий получатель тикета может поменять адрес получателя, если тикет еще не следующий на выплату. + +## Аргументы инструкций + +`init` аргументов не принимает. + +`update_coef_limit`: + +- `coef_ppm: u64` +- `limit_usd_cents: u64` +- `call_reward_lamports: u64` + +`grant_manager_limits`: + +- `manager_wallet: Pubkey` +- `add_q1_usd_cents: u64` +- `add_q2_usd_cents: u64` + +`buy_ticket`: + +- `amount_lamports: u64` +- `recipient_wallet: Pubkey` + +`buy_ticket_usd`: + +- `amount_usd_cents: u64` +- `max_pay_lamports: u64` +- `recipient_wallet: Pubkey` + +`buy_ticket_sol`: + +- `amount_lamports: u64` +- `min_expected_usd_cents: u64` +- `recipient_wallet: Pubkey` + +`manager_add_ticket`: + +- `queue_id: u8` — только `1` или `2` +- `recipient_wallet: Pubkey` +- `payout_usd_cents: u64` + +`change_ticket_recipient`: + +- `new_recipient_wallet: Pubkey` + +## Главные PDA + +1. `config_pda` + - Seed: `shine_payments_config`. + - Хранит `dao_wallet` и `inflow_vault`. + - Размер PDA: `8 + 160` байт. + +2. `coef_limit_pda` + - Seed: `shine_payments_coef_limit`. + - Хранит коэффициент выплат, лимит и награду `step_payout`. + - Размер PDA: `8 + 96` байт. + +3. `queues_pda` + - Seed: `shine_payments_queues`. + - Хранит агрегаты очередей Q1/Q2. + - Размер PDA: `8 + 192` байт. + +4. `inflow_vault_pda` + - Seed: `shine_payments_inflow_vault`. + - Принимает деньги от `shine_users`. + - Из него выполняются выплаты тикетам, DAO и вызывающему `step_payout`. + - Размер PDA: `8 + 32` байт. + +5. `ticket_pda` + - Seed зависит от очереди и индекса тикета. + - Отдельная PDA-запись на каждый тикет. + - Q1 seed: `shine_payments_q1_ticket` + `ticket_index`. + - Q2 seed: `shine_payments_q2_ticket` + `ticket_index`. + - Размер PDA: `8 + 160` байт. + +6. `manager_allowance_pda` + - Seed: `shine_p_manager_allow` + адрес менеджера. + - Хранит доступный лимит менеджера по Q1/Q2. + - Размер PDA: `8 + 128` байт. + +## Текущие параметры + +Параметры initial config из `programs/shine_payments/src/settings.rs`: + +| Поле | Значение | Смысл | +| --- | --- | --- | +| `START_COEF_PPM` | `5_000_000` | коэффициент 5.0x в ppm-масштабе | +| `START_LIMIT_USD_CENTS` | `1_000_000` | стартовый лимит Q1: 10_000 USD | +| `START_CALL_REWARD_LAMPORTS` | `8_000_000` | награда вызвавшему `step_payout`, 0.008 SOL | +| `MAX_CALL_REWARD_LAMPORTS` | `10_000_000` | максимум награды, 0.01 SOL | +| `ORACLE_MAX_AGE_SECS` | `120` | максимальный возраст цены Pyth | + +Для расчетов используется Pyth SOL/USD: + +- feed id: `0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d` +- price update account: `7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE` + +## Деньги + +Входы: + +- из `shine_users` в `inflow_vault_pda` при регистрации и увеличении лимита; +- от покупателя тикета сразу в `dao_wallet` при `buy_ticket*`. + +Выходы: + +- из `inflow_vault_pda` получателю тикета; +- из `inflow_vault_pda` в `dao_wallet`; +- из `inflow_vault_pda` вызвавшему `step_payout`; +- если очереди пустые, весь доступный остаток `inflow_vault_pda` переводится в DAO. + +## Очереди и выплаты + +Выплаты идут строго пошагово: + +- если есть невыплаченные Q1-тикеты, `step_payout` берет следующий Q1; +- если Q1 пустая, берется следующий Q2; +- для Q1 DAO-часть равна сумме тикета в USD; +- для Q2 DAO-часть равна двойной сумме тикета в USD; +- перед выплатой суммы пересчитываются из USD-центов в lamports по Pyth SOL/USD; +- если в `inflow_vault_pda` не хватает средств на тикет, DAO-часть и награду вызвавшему, шаг отклоняется. + +`change_ticket_recipient` запрещает менять получателя у тикета, который является следующим на выплату. + +## Ключи и управление + +На старте удобно считать, что у программы есть отдельный управляющий ключ `key_3`. + +Целевая модель: + +- `update_coef_limit` вызывает DAO; +- `grant_manager_limits` вызывает DAO; +- upgrade-authority программы после проверки передается DAO; +- `step_payout` остается открытым для любого подписанта, чтобы выплаты не зависели от одного оператора. diff --git a/Dev_Docs/Solana_Architecture/details/shine_users.md b/Dev_Docs/Solana_Architecture/details/shine_users.md new file mode 100644 index 0000000..d8e7004 --- /dev/null +++ b/Dev_Docs/Solana_Architecture/details/shine_users.md @@ -0,0 +1,136 @@ +# `shine_users` + +## Кратко + +`shine_users` — вторая программа Solana-модуля SHiNE. Она отвечает за создание и обновление пользовательской PDA-записи, проверку подписи записи, проверку логина через `shine_login_guard` и оплату регистрации/дополнительного лимита. + +Папка программы: `shine-solana/shine/programs/shine_users/`. + +## Текущие функции + +1. `init_users_economy_config` + - Создает PDA с экономическими настройками пользователей. + - Записывает стартовую регистрационную комиссию, цену шага лимита и стартовый бонус лимита. + +2. `update_users_economy_config` + - Обновляет экономические настройки. + - Требует подпись `DAO_AUTHORITY` из общего deploy-конфига. + +3. `create_user_pda` + - Проверяет логин через `shine_login_guard`. + - Проверяет структуру полей пользователя. + - Проверяет подпись записи root-ключом пользователя. + - Создает `user_pda` по seed `login=`. + - Переводит оплату регистрации и дополнительного лимита в `shine_payments::inflow_vault_pda`. + +4. `update_user_pda` + - Проверяет неизменяемые поля пользователя. + - Проверяет `prev_hash`, новую подпись и новое состояние последнего блока. + - При необходимости расширяет PDA. + - Переводит оплату дополнительного лимита в `shine_payments::inflow_vault_pda`. + +## Аргументы инструкций + +`init_users_economy_config` аргументов не принимает. + +`update_users_economy_config`: + +- `registration_fee_lamports: u64` +- `lamports_per_limit_step: u64` +- `start_bonus_limit: u64` + +`create_user_pda`: + +- `login: String` +- `root_key: Pubkey` +- `created_at_ms: u64` +- `additional_limit: u64` +- `fields: UserMutableFields` +- `signature: Vec` + +`update_user_pda`: + +- `login: String` +- `root_key: Pubkey` +- `created_at_ms: u64` +- `updated_at_ms: u64` +- `version: u32` +- `prev_hash: Vec` +- `additional_limit: u64` +- `fields: UserMutableFields` +- `signature: Vec` + +`UserMutableFields`: + +- `device_key: Pubkey` +- `blockchain_public_key: Pubkey` +- `blockchain_name: String` +- `used_bytes: u64` +- `last_block_number: u32` +- `last_block_hash: Vec` — ровно 32 байта +- `last_block_signature: Vec` — ровно 64 байта +- `arweave_tx_id: String` +- `is_server: bool` +- `server_key: Pubkey` +- `server_address: String` +- `sync_servers: Vec` +- `access_servers: Vec` +- `trusted_count: u8` + +## Главные PDA + +1. `user_pda` + - PDA записи пользователя. + - Seed: `login=`. + - Создается отдельно для каждого логина. + - Стартовый размер: `768` байт. + - При обновлении может расширяться через `realloc`, но один auto-realloc ограничен `10_000` байт. + +2. `users_economy_config_pda` + - PDA с настройками экономики. + - Seed: `shine_users_economy_config`. + - Хранит регистрационную комиссию, цену шага лимита и стартовый бонус. + - Размер PDA: `8 + 96` байт. + +## Текущие параметры экономики + +Параметры initial config из `programs/shine_users/src/settings.rs`: + +| Поле | Значение | Смысл | +| --- | --- | --- | +| `START_REGISTRATION_FEE_LAMPORTS` | `10_000_000` | стартовая комиссия регистрации, 0.01 SOL | +| `LIMIT_STEP` | `10_000` | шаг `additional_limit` | +| `START_LAMPORTS_PER_LIMIT_STEP` | `100_000` | 0.0001 SOL за один шаг лимита | +| `START_BONUS_LIMIT` | `100_000` | стартовый бесплатный лимит при регистрации | + +`additional_limit` в create/update должен быть кратен `LIMIT_STEP`. + +## Связь с другими программами + +`shine_users` зависит от: + +- `shine_login_guard` — для проверки логина при создании пользователя; +- `shine_payments` — для вычисления и проверки `inflow_vault_pda`, куда уходят платежи. + +`create_user_pda` делает CPI-вызов `shine_login_guard::classify_login` и принимает только результат `0`. Premium/trademark логины сейчас отклоняются ошибками `PremiumLogin` или `TrademarkLoginRequiresReview`. + +Подпись `user_pda` и подпись состояния последнего блока проверяются через встроенную Solana Ed25519-инструкцию, которая должна идти раньше инструкции `shine_users` в той же транзакции. + +## Деньги + +Деньги из `shine_users` идут только в `inflow_vault_pda` программы `shine_payments`. + +Потоки: + +- `create_user_pda`: регистрационная комиссия + оплата `additional_limit`; +- `update_user_pda`: оплата `additional_limit`, если она больше нуля. + +## Ключи и управление + +На старте удобно считать, что у программы есть отдельный управляющий ключ `key_2`. + +Целевая модель: + +- economy-настройки меняет DAO-authority; +- upgrade-authority программы после проверки передается DAO; +- пользовательские операции `create_user_pda` и `update_user_pda` остаются доступными обычным пользователям при корректных подписях и оплате. diff --git a/Dev_Docs/Solana_Architecture/schemes/architecture.mmd b/Dev_Docs/Solana_Architecture/schemes/architecture.mmd new file mode 100644 index 0000000..978afc1 --- /dev/null +++ b/Dev_Docs/Solana_Architecture/schemes/architecture.mmd @@ -0,0 +1,54 @@ +flowchart LR + U[Пользователь / signer] + B[Покупатель тикета] + M[Менеджер] + C[Любой caller step_payout] + + LG[1. shine_login_guard
classify_login] + USERS[2. shine_users
create_user_pda / update_user_pda] + PAY[3. shine_payments
vault / tickets / payouts] + DAO[SHiNE DAO
governance / authority / treasury] + + USERPDA[(user_pda
по login)] + ECON[(users_economy_config_pda)] + CONFIG[(config_pda)] + COEF[(coef_limit_pda)] + QUEUES[(queues_pda)] + VAULT[(inflow_vault_pda)] + TICKET[(ticket_pda)] + ALLOW[(manager_allowance_pda)] + + U -->|логин| USERS + USERS -->|CPI проверка| LG + USERS -->|создает/обновляет| USERPDA + USERS -->|читает экономику| ECON + U -->|регистрация / лимит| VAULT + + DAO -->|update economy| USERS + DAO -->|update coef/limit| PAY + DAO -->|grant manager limits| PAY + DAO -->|создает/отзывает ключи| DAO + + PAY --> CONFIG + PAY --> COEF + PAY --> QUEUES + PAY --> VAULT + PAY --> TICKET + PAY --> ALLOW + + B -->|buy_ticket*| PAY + B -->|оплата покупки тикета| DAO + PAY -->|создает тикет| TICKET + + M -->|manager_add_ticket| PAY + ALLOW -->|лимиты Q1/Q2| M + + C -->|step_payout| PAY + VAULT -->|выплата тикета| U + VAULT -->|DAO-часть| DAO + VAULT -->|call reward| C + + DAO -. upgrade authority после передачи .-> USERS + DAO -. upgrade authority после передачи .-> PAY + DAO -. позже возможно .-> LG + diff --git a/Dev_Docs/Solana_Architecture/schemes/architecture.png b/Dev_Docs/Solana_Architecture/schemes/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000000000000000000000000000..0f1a060d405847d6972d4848b9a16172ccf6ff0eb7327977fb72bf903a30efe4 GIT binary patch literal 239574 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≻d)R7v;*mVC4yI8xi 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 + Архитектура Solana-программ SHiNE + Схема трех программ, DAO, PDA-счетов и движения денег. + + + + + + + + + + + + SHiNE Solana: программы, DAO, счета и движение денег + Текущая модель: три Anchor-программы, DAO/authority как управляющий слой, inflow vault и DAO treasury. + + + Пользователь + signer, root_key, device_key + + + Покупатель тикета + buy_ticket* + + + Менеджер + manager_add_ticket + + + Любой caller + step_payout + + + 1. shine_login_guard + classify_login + free / premium / trademark + + + 2. shine_users + create_user_pda + update_user_pda + economy config + + + 3. shine_payments + vault, tickets, queues + grant_manager_limits + step_payout + + + SHiNE DAO + governance / authority + treasury dao_wallet + ключи через голосование + + + shine_users PDA + user_pda, economy_config + + + shine_payments PDA + config_pda, coef_limit_pda + queues_pda + inflow_vault_pda + ticket_pda, manager_allowance + + + inflow_vault + деньги регистрации + + + DAO treasury + dao_wallet + + + регистрация / update + + + CPI login + + + создает/обновляет + + + регистрация и лимит -> inflow_vault + + + покупка тикета -> DAO treasury + + + создать тикет + + + PDA состояния + + + + + call reward caller + + + выплата получателю тикета + + + DAO-часть выплат + + + update economy + + + settings / managers + + + upgrade-authority: users/payments; login_guard позже + + + + логические вызовы и управление + + движение SOL/lamports + + будущая передача upgrade-authority DAO + diff --git a/Dev_Docs/Инициализация_Solana_регистрации/README.md b/Dev_Docs/Инициализация_Solana_регистрации/README.md new file mode 100644 index 0000000..450c10c --- /dev/null +++ b/Dev_Docs/Инициализация_Solana_регистрации/README.md @@ -0,0 +1,91 @@ +# Деплой и инициализация Solana-регистрации (две обязательные программы) + +## Коротко + +Для рабочей регистрации пользователя нужны **обе** программы: + +1. `shine_users` — хранение и обновление `user_pda`, economy-конфиг, логика регистрации. +2. `shine_login_guard` — проверка/классификация логина (CPI из `shine_users`). + +Если задеплоена только одна из них — регистрация неработоспособна. + +## Актуальные адреса (devnet) + +- `shine_users` (регистрация пользователей): + `FZS1YctoeEhCkZ5VTjsysUFAXR8CqxYztcLboXcg2Rpm` +- `shine_login_guard`: + `3xkopA7cXagxzMFrKdv3NCBfV6BKiRJCk69kr27M2sRo` +- `shine_payments`: + `m48pWRGWrMj3TEHjuU4zsp5Gju4e7ZaPovk8RcVt7kR` + +## Подтверждение деплоя + +- Сеть: `https://api.devnet.solana.com` +- `shine_users`: + - `Program ID`: `FZS1YctoeEhCkZ5VTjsysUFAXR8CqxYztcLboXcg2Rpm` + - TX deploy: `5VzfpSirFCRqPUZfvAt3eADY9KnowW79PKZ1pCQAa2DJGiztj4dUYYXrSQNmWEhPVu6mPSDfcuHzFyEVmoKLa9DM` +- `shine_login_guard`: + - `Program ID`: `3xkopA7cXagxzMFrKdv3NCBfV6BKiRJCk69kr27M2sRo` + - TX deploy: `5iptngPYrLLjPE3Xby24zyNW3edVUnBNLBx785vjojMoq5JNLFNQvLNAm3jNYHbpf2B36qtbpTNzcvUNyRDqm1Mf` + +## Порядок деплоя (devnet) + +1. Убедиться, что CLI смотрит в devnet и у кошелька есть SOL. +2. Собрать и задеплоить `shine_login_guard`. +3. Собрать и задеплоить `shine_users`. +4. Проверить, что адреса совпадают между: + - `Anchor.toml` + - `declare_id!` в `programs/*/src/lib.rs` + - UI/серверными константами. +5. Выполнить `init_users_economy_config` (один раз на программу `shine_users`). + +Пример команд: + +```bash +cd shine-solana/shine +solana config get +solana balance + +anchor build -p shine_login_guard +anchor deploy -p shine_login_guard + +anchor build -p shine_users +anchor deploy -p shine_users +``` + +## Куда вписаны адреса в проекте + +### UI + +- Общие Solana-константы: + - `shine-UI/js/solana-programs.js` +- Страница инициализации: + - `shine-UI/js/pages/solana-users-init-view.js` +- Переход на страницу: + - `shine-UI/js/pages/developer-settings-view.js` + +### Сервер + +- Серверные константы Solana: + - `shine-server-config/src/main/java/utils/config/SolanaProgramsConfig.java` + +## Как запустить инициализацию economy PDA + +1. Открыть UI. +2. Перейти: `Профиль -> Настройки -> Настройки разработчика -> Solana: init регистрации`. +3. Подключить кошелёк (Phantom, devnet). +4. Нажать `Запустить init_users_economy_config`. +5. Дождаться статуса `Успешно`. + +Страница сама вычисляет PDA `users_economy_config` по seed: + +- seed: `shine_users_economy_config` +- program: `FZS1YctoeEhCkZ5VTjsysUFAXR8CqxYztcLboXcg2Rpm` + +## Важно + +- `init_users_economy_config` выполняется один раз на программу. + Если PDA уже создан, повторный вызов вернёт ошибку "already initialized" (это нормальное поведение). +- Серверные приватные ключи для Solana не используются: подписание делается кошельком пользователя в UI. +- `shine_users` внутри `create_user_pda` требует корректный адрес `shine_login_guard` для CPI-классификации логина. + Несовпадение адреса приведёт к ошибке регистрации. diff --git a/Players/blackbyrd1/files/.gitkeep b/Players/blackbyrd1/files/.gitkeep new file mode 100644 index 0000000..4c0d52d --- /dev/null +++ b/Players/blackbyrd1/files/.gitkeep @@ -0,0 +1 @@ + diff --git a/Players/blackbyrd1/history/.gitkeep b/Players/blackbyrd1/history/.gitkeep new file mode 100644 index 0000000..4c0d52d --- /dev/null +++ b/Players/blackbyrd1/history/.gitkeep @@ -0,0 +1 @@ + diff --git a/Players/dimasol1/files/.gitkeep b/Players/dimasol1/files/.gitkeep new file mode 100644 index 0000000..4c0d52d --- /dev/null +++ b/Players/dimasol1/files/.gitkeep @@ -0,0 +1 @@ + diff --git a/Players/dimasol1/history/.gitkeep b/Players/dimasol1/history/.gitkeep new file mode 100644 index 0000000..4c0d52d --- /dev/null +++ b/Players/dimasol1/history/.gitkeep @@ -0,0 +1 @@ + diff --git a/Players/malvviiina/files/.gitkeep b/Players/malvviiina/files/.gitkeep new file mode 100644 index 0000000..4c0d52d --- /dev/null +++ b/Players/malvviiina/files/.gitkeep @@ -0,0 +1 @@ + diff --git a/Players/malvviiina/history/.gitkeep b/Players/malvviiina/history/.gitkeep new file mode 100644 index 0000000..4c0d52d --- /dev/null +++ b/Players/malvviiina/history/.gitkeep @@ -0,0 +1 @@ + diff --git a/Players/oidasyda/files/.gitkeep b/Players/oidasyda/files/.gitkeep new file mode 100644 index 0000000..4c0d52d --- /dev/null +++ b/Players/oidasyda/files/.gitkeep @@ -0,0 +1 @@ + diff --git a/Players/oidasyda/history/.gitkeep b/Players/oidasyda/history/.gitkeep new file mode 100644 index 0000000..4c0d52d --- /dev/null +++ b/Players/oidasyda/history/.gitkeep @@ -0,0 +1 @@ + diff --git a/Players/zodiaktechnika32/files/.gitkeep b/Players/zodiaktechnika32/files/.gitkeep new file mode 100644 index 0000000..4c0d52d --- /dev/null +++ b/Players/zodiaktechnika32/files/.gitkeep @@ -0,0 +1 @@ + diff --git a/Players/zodiaktechnika32/history/.gitkeep b/Players/zodiaktechnika32/history/.gitkeep new file mode 100644 index 0000000..4c0d52d --- /dev/null +++ b/Players/zodiaktechnika32/history/.gitkeep @@ -0,0 +1 @@ + diff --git a/SHiNE-agent-bot-coder/.env.example b/SHiNE-agent-bot-coder/.env.example index a9db23f..34aafdf 100644 --- a/SHiNE-agent-bot-coder/.env.example +++ b/SHiNE-agent-bot-coder/.env.example @@ -1,9 +1,12 @@ TELEGRAM_BOT_TOKEN=replace_me OPENAI_API_KEY=replace_me ALLOWED_TELEGRAM_USERNAME=AidarKC +ALLOWED_TELEGRAM_PLAYERS=malvviiina:Милана,zodiaktechnika32:Сергей,oidasyda:Иван,blackbyrd1:Ворон,dimasol1:Дима ALLOWED_TELEGRAM_CHANNEL_USERNAME=shine_writing BOT_USERNAME=aidar_su_bot OPENAI_TRANSCRIBE_MODEL=gpt-4o-mini-transcribe +TELEGRAM_FILE_DOWNLOAD_TIMEOUT_SECONDS=300 +OPENAI_TRANSCRIBE_TIMEOUT_SECONDS=900 CODEX_BIN=/home/ai/.cache/JetBrains/IntelliJIdea2026.1/aia/codex/bin/codex-x86_64-unknown-linux-musl CODEX_WORKDIR=/home/ai/work/SHiNE/SHiNE-server-sha256 CODEX_TIMEOUT_SECONDS=900 diff --git a/SHiNE-agent-bot-coder/AGENT.md b/SHiNE-agent-bot-coder/AGENT.md index be17045..6bc7319 100644 --- a/SHiNE-agent-bot-coder/AGENT.md +++ b/SHiNE-agent-bot-coder/AGENT.md @@ -15,19 +15,33 @@ ## Авторитет команд и история - Основной пользователь и источник команд — Айдар: `@AidarKC` / `@aidarkc`. -- Агент должен выполнять то, что говорит Айдар; сообщения других пользователей считать дополнительным контекстом, а не командами к исполнению. -- Сообщения других пользователей в разрешённом канале, группе или supergroup сохраняются в историю диалога как контекстные сообщения. -- На сообщения других пользователей в группе или supergroup сервис должен коротко отвечать в тот же чат, что сообщение получено, но не ставить их в очередь как задачи. -- Использовать сообщения других пользователей для действий нужно только если Айдар дал на это специальную инструкцию. -- В Telegram-канале/группе `@shine_writing` сервис должен отвечать только на сообщения Айдара, а ответы отправлять в тот же чат. +- Дополнительно разрешены игроки из whitelist (`ALLOWED_TELEGRAM_PLAYERS`), каждый со своей отдельной историей и рабочей папкой `Players//`. +- Игроки работают в режиме вопросов/анализа/подготовки материалов: в промпте явно задано правило не менять код проекта и писать материалы только в своей папке. +- Для неизвестных пользователей в личном чате сервис отвечает вежливым отказом. +- В Telegram-канале/группе `@shine_writing` сервис выполняет сообщения только от Айдара, а ответы отправляет в тот же чат. - Если Telegram сообщает о миграции обычной группы в supergroup, сервис должен запомнить новый `chat_id` и отправлять ответы уже туда. +- На события подключения/отключения пользователей (join/leave) сервис не отвечает и ничего не отправляет. ## Очередь и состояние - Входящие задачи записываются в файловую очередь и обрабатываются строго по одной, чтобы не смешивать изменения в проекте. - Сервис ведёт состояние активной задачи и текущего файла истории, а после рестарта продолжает незавершённую обработку с учётом сохранённого состояния. -- Истории диалогов хранятся в JSONL; после команды `/new` старая история архивируется, а новая начинается отдельно. +- Истории диалогов хранятся в JSONL по каждому разрешённому username отдельно: `data/history//`. +- Архив истории после `/new`: `data/history//archive/`. +- Для просмотра истории игрока открывать файлы в его папке истории по username. - Дедупликация входящих Telegram update нужна, чтобы одно сообщение не попало в обработку повторно. - Если Codex молчит во время активной задачи 2 минуты подряд, сервис отправляет аварийный статус с общим временем работы задачи; при дальнейшем молчании повторяет статус каждые 2 минуты. +- После успешной обработки задачи из личного чата Айдара сервис должен отправить публичный итоговый отчёт в группу `@shine_writing`: первым сообщением исходный запрос, вторым сообщением-ответом итоговый ответ Codex. Промежуточные статусы в группу не дублировать. +- Для приватных voice/audio-запросов в публичном отчёте первым сообщением отправлять исходный Telegram voice/audio-файл с подписью, где указан распознанный текст. В пользовательском тексте отчёта не показывать Telegram `file_id`. + +## Планы и отложенные фичи +- Планы проекта по отложенным фичам хранятся в `Dev_Docs/Future_Features/`. +- Внутри есть три горизонта: + - `near/` - ближайшие планы, обычно сегодня/завтра; + - `medium/` - среднесрочные планы, обычно недели или 1-2 месяца; + - `far/` - дальнее будущее без понятного срока. +- Если пользователь спрашивает, какие есть планы или что можно продолжить, нужно смотреть эти три папки и отвечать кратким списком по горизонтам. +- Файлы из `Dev_Docs/Future_Features/` не начинать реализовывать без явной команды пользователя. +- После реализации фичи, требующей ручной проверки, нужно добавить отдельный файл в `Dev_Docs/Pending_Features/`. ## Локальный запуск и systemd - Основной запуск сервиса выполняется Python-скриптом `py_bot_service.py` из папки `SHiNE-agent-bot-coder/`. @@ -35,7 +49,7 @@ - Для проверки Codex без Telegram можно использовать self-test режим сервиса. - Для постоянного локального запуска используется user-level systemd service `shine-agent-bot-coder`; скрипты установки лежат в `SHiNE-agent-bot-coder/scripts/systemd/`. - Если меняется логика сервиса, после изменений нужно проверить запуск локально и при необходимости перезапустить user systemd service. -- Команда Telegram `/restart_service` перезапускает сервис через завершение процесса; systemd поднимает его заново. Короткий алиас: `/restart`. +- Команда Telegram `/restart_service` (и алиас `/restart`) доступна только Айдару. ## Правила ответа - Пиши содержательно и коротко. diff --git a/SHiNE-agent-bot-coder/AGENTS.md b/SHiNE-agent-bot-coder/AGENTS.md new file mode 100644 index 0000000..20aa593 --- /dev/null +++ b/SHiNE-agent-bot-coder/AGENTS.md @@ -0,0 +1,25 @@ +# AGENTS + +## Назначение +- Это автоматически читаемые инструкции Codex для папки `SHiNE-agent-bot-coder/`. +- `SHiNE-agent-bot-coder` — локальный Telegram-бот-сервис агента-кодера для работы с проектом SHiNE. +- Если пользователь говорит «агент MD», «агент с MD» или похожим образом про файл инструкций Codex, считать, что имеется в виду `AGENTS.md`. + +## Связанные инструкции +- Подробные служебные правила Telegram-обработчика лежат в `AGENT.md`. +- `AGENT.md` используется самим сервисом как файл инструкций, который передаётся в промпт обработчика входящих Telegram-сообщений. +- При изменении логики сервиса сначала читать `AGENT.md`, затем код `py_bot_service.py`. + +## Планы и задачи +- Отложенные задачи проекта лежат в `../Dev_Docs/Future_Features/`. +- Точка входа по планам: `../Dev_Docs/Future_Features/README.md`. +- Горизонты планов: + - `near/` - ближайшие планы; + - `medium/` - среднесрочные планы; + - `far/` - дальнее будущее. +- Если пользователь спрашивает, какие есть планы или что можно продолжить, кратко перечислять задачи по этим горизонтам. +- Не начинать реализацию задач из `Future_Features` без явной команды пользователя. + +## Проверка после изменений +- Если меняется логика Telegram-бота, проверить локальный запуск или self-test, когда это уместно. +- Если меняется только документация или инструкции, достаточно проверить, что ссылки на документы актуальны. diff --git a/SHiNE-agent-bot-coder/Players/PROMPTS_REVIEW.md b/SHiNE-agent-bot-coder/Players/PROMPTS_REVIEW.md new file mode 100644 index 0000000..edeae1b --- /dev/null +++ b/SHiNE-agent-bot-coder/Players/PROMPTS_REVIEW.md @@ -0,0 +1,26 @@ +# Промпты для режима игроков (на согласование) + +## 1) Базовый служебный промпт (добавка к задаче игрока) + +```text +Режим игрока (обязательно): +- Пользователь: <Имя> (@). +- Рабочая папка игрока: /Players/ +- Код проекта не изменять. +- Можно отвечать на вопросы по проекту, предлагать идеи и готовить ТЗ. +- Если нужны правки кода, описывать предложение текстом и сохранять материалы только в папке игрока. +``` + +## 2) Приветственное сообщение игроку (один раз) + +```text +Привет, <Имя>. +Можно задавать вопросы по проекту, просить анализ, идеи и подготовку готового ТЗ. +Команда /new начинает новую сессию и архивирует текущую историю. +``` + +## 3) Отказ неизвестному пользователю + +```text +Извините, доступ к этому агенту пока не выдан. Обратитесь к Айдару. +``` diff --git a/SHiNE-agent-bot-coder/README.md b/SHiNE-agent-bot-coder/README.md index 38d171c..c00349f 100644 --- a/SHiNE-agent-bot-coder/README.md +++ b/SHiNE-agent-bot-coder/README.md @@ -2,6 +2,7 @@ Локальный Telegram-бот-сервис для пользователя `ai`: - принимает сообщения от `@AidarKC`; +- поддерживает whitelist игроков (`ALLOWED_TELEGRAM_PLAYERS`) с отдельными историями; - ведёт историю диалога в `JSONL`; - ставит задачи в файловую очередь; - обрабатывает задачи строго последовательно; @@ -9,8 +10,7 @@ - вызывает Codex CLI и отправляет ответ в Telegram; - при рестарте восстанавливает незавершённые задачи; - отправляет аварийный статус только если Codex молчит 2 минуты подряд во время активной задачи; -- принимает сообщения из канала/группы `@shine_writing`, выполняет команды только от `@AidarKC`, а сообщения других авторов сохраняет как контекст; -- на сообщения других участников группы отвечает в тот же чат коротким подтверждением получения, не создавая задачу Codex; +- принимает сообщения из канала/группы `@shine_writing`, выполняет команды только от `@AidarKC`; - учитывает миграцию обычной Telegram-группы в supergroup и перенаправляет ответы на новый `chat_id`. Рабочая реализация сервиса — только `py_bot_service.py`. Старая Java-реализация удалена, потому что не заработала и больше не используется. @@ -20,8 +20,8 @@ - `data/py_queue.jsonl` — очередь Python-сервиса; - `data/py_state.json` — текущее состояние Python-сервиса; - `data/py_processed_updates.log` — дедуп входящих update; -- `data/history/*.jsonl` — активные истории; -- `data/history/archive/*.jsonl` — архив историй после `/new`. +- `data/history//*.jsonl` — активные истории по пользователям; +- `data/history//archive/*.jsonl` — архивы после `/new`. ## Локальный запуск 1. Скопировать пример: @@ -29,7 +29,10 @@ 2. Заполнить секреты в `.env`. - `TELEGRAM_BOT_TOKEN` — токен рабочего Telegram-бота. - `ALLOWED_TELEGRAM_USERNAME` — пользователь, чьи сообщения выполняются как команды. + - `ALLOWED_TELEGRAM_PLAYERS` — whitelist игроков в формате `username:Имя,username2:Имя2`. - `ALLOWED_TELEGRAM_CHANNEL_USERNAME` — канал, из которого принимаются `channel_post`; обычные group/supergroup-сообщения обрабатываются как `message`. + - `TELEGRAM_FILE_DOWNLOAD_TIMEOUT_SECONDS` — тайм-аут скачивания voice/audio из Telegram, по умолчанию 300 секунд. + - `OPENAI_TRANSCRIBE_TIMEOUT_SECONDS` — тайм-аут распознавания voice/audio в OpenAI, по умолчанию 900 секунд. 3. Запуск: - `python3 SHiNE-agent-bot-coder/py_bot_service.py` @@ -59,4 +62,4 @@ python3 SHiNE-agent-bot-coder/py_bot_service.py --selftest-codex "Ответь - `/stop` — остановить текущую задачу. - `/cancel ` — удалить задачу по id/префиксу или очистить очередь. - `/new` — архивировать текущую историю и начать новый диалог. -- `/restart_service` — перезапустить сервис; systemd должен поднять процесс заново. +- `/restart_service` — перезапустить сервис (только для Айдара); systemd должен поднять процесс заново. diff --git a/SHiNE-agent-bot-coder/py_bot_service.py b/SHiNE-agent-bot-coder/py_bot_service.py index 9159315..dee95c8 100644 --- a/SHiNE-agent-bot-coder/py_bot_service.py +++ b/SHiNE-agent-bot-coder/py_bot_service.py @@ -14,11 +14,20 @@ import subprocess import tempfile import threading import time +import traceback import uuid from pathlib import Path from typing import Any from urllib import error, request +DEFAULT_ALLOWED_PLAYERS = ",".join([ + "malvviiina:Милана", + "zodiaktechnika32:Сергей", + "oidasyda:Иван", + "blackbyrd1:Ворон", + "dimasol1:Дима", +]) + def now_iso() -> str: return dt.datetime.now(dt.timezone.utc).isoformat() @@ -33,6 +42,21 @@ def normalize_username(value: str | None) -> str: return value.lower() +def parse_allowed_players(raw: str) -> dict[str, str]: + players: dict[str, str] = {} + for item in (raw or "").split(","): + part = item.strip() + if not part: + continue + username_part, sep, name_part = part.partition(":") + username = normalize_username(username_part) + if not username: + continue + player_name = (name_part if sep else username_part).strip() or username + players[username] = player_name + return players + + def split_long_text(text: str, chunk_size: int = 3500) -> list[str]: text = (text or "").strip() if not text: @@ -55,6 +79,27 @@ def read_env_file(path: Path) -> dict[str, str]: return result +class VoiceTranscriptionError(RuntimeError): + def __init__( + self, + user_message: str, + *, + stage: str, + retryable: bool = True, + detail: str = "", + ): + super().__init__(user_message) + self.user_message = user_message + self.stage = stage + self.retryable = retryable + self.detail = detail + + def log_text(self) -> str: + if self.detail and self.detail != self.user_message: + return f"{self.user_message} stage={self.stage} retryable={self.retryable} detail={self.detail}" + return f"{self.user_message} stage={self.stage} retryable={self.retryable}" + + class JsonLineStore: @staticmethod def load(path: Path) -> list[dict[str, Any]]: @@ -116,11 +161,39 @@ class TelegramApi: result = self.call("getUpdates", payload=payload, timeout=timeout_sec + 15) return result.get("result", []) - def send_message(self, chat_id: int, text: str, reply_to_message_id: int | None = None) -> None: + def send_message(self, chat_id: int | str, text: str, reply_to_message_id: int | None = None) -> dict[str, Any]: payload: dict[str, Any] = {"chat_id": chat_id, "text": text} if reply_to_message_id is not None: payload["reply_to_message_id"] = reply_to_message_id - self.call("sendMessage", payload=payload, timeout=30) + return self.call("sendMessage", payload=payload, timeout=30) + + def send_voice( + self, + chat_id: int | str, + voice: str, + caption: str = "", + reply_to_message_id: int | None = None, + ) -> dict[str, Any]: + payload: dict[str, Any] = {"chat_id": chat_id, "voice": voice} + if caption: + payload["caption"] = caption + if reply_to_message_id is not None: + payload["reply_to_message_id"] = reply_to_message_id + return self.call("sendVoice", payload=payload, timeout=60) + + def send_audio( + self, + chat_id: int | str, + audio: str, + caption: str = "", + reply_to_message_id: int | None = None, + ) -> dict[str, Any]: + payload: dict[str, Any] = {"chat_id": chat_id, "audio": audio} + if caption: + payload["caption"] = caption + if reply_to_message_id is not None: + payload["reply_to_message_id"] = reply_to_message_id + return self.call("sendAudio", payload=payload, timeout=60) def delete_webhook(self) -> None: self.call("deleteWebhook", payload={"drop_pending_updates": False}, timeout=30) @@ -134,10 +207,13 @@ class BotConfig: self.root_dir = root_dir self.telegram_bot_token = self._required(env, "TELEGRAM_BOT_TOKEN") self.allowed_username = normalize_username(env.get("ALLOWED_TELEGRAM_USERNAME", "AidarKC")) + self.allowed_players = parse_allowed_players(env.get("ALLOWED_TELEGRAM_PLAYERS", DEFAULT_ALLOWED_PLAYERS)) self.allowed_channel_username = normalize_username(env.get("ALLOWED_TELEGRAM_CHANNEL_USERNAME", "shine_writing")) self.bot_username = env.get("BOT_USERNAME", "aidar_su_bot") self.openai_api_key = env.get("OPENAI_API_KEY", "").strip() self.openai_transcribe_model = env.get("OPENAI_TRANSCRIBE_MODEL", "gpt-4o-mini-transcribe") + self.telegram_file_download_timeout_seconds = int(env.get("TELEGRAM_FILE_DOWNLOAD_TIMEOUT_SECONDS", "300")) + self.openai_transcribe_timeout_seconds = int(env.get("OPENAI_TRANSCRIBE_TIMEOUT_SECONDS", "900")) self.codex_bin = Path(env.get( "CODEX_BIN", "/home/ai/.cache/JetBrains/IntelliJIdea2026.1/aia/codex/bin/codex-x86_64-unknown-linux-musl" @@ -185,6 +261,20 @@ class ShinePyBotService: self.last_heartbeat_at: float = 0.0 self.restart_requested = False + def _is_owner(self, username: str) -> bool: + return normalize_username(username) == self.cfg.allowed_username + + def _is_allowed_player(self, username: str) -> bool: + return normalize_username(username) in self.cfg.allowed_players + + def _is_allowed_user(self, username: str) -> bool: + uname = normalize_username(username) + return uname == self.cfg.allowed_username or uname in self.cfg.allowed_players + + def _player_name(self, username: str) -> str: + uname = normalize_username(username) + return self.cfg.allowed_players.get(uname, uname) + def run(self) -> None: self._ensure_dirs() self._acquire_single_instance_lock() @@ -250,9 +340,16 @@ class ShinePyBotService: self.state = json.loads(self.state_file.read_text(encoding="utf-8")) else: self.state = {} + sessions = self.state.get("user_sessions") + if not isinstance(sessions, dict): + sessions = {} + self.state["user_sessions"] = sessions if not self.state.get("current_history_file"): - history_file = self._create_new_history_file("initial") + history_file = self._create_new_history_file("initial", self.cfg.allowed_username) self.state["current_history_file"] = str(history_file) + sessions[self.cfg.allowed_username] = {"current_history_file": str(history_file)} + elif self.cfg.allowed_username not in sessions: + sessions[self.cfg.allowed_username] = {"current_history_file": str(self.state["current_history_file"])} if not isinstance(self.state.get("next_job_number"), int): self.state["next_job_number"] = 1 self.state["updated_at"] = now_iso() @@ -320,26 +417,70 @@ class ShinePyBotService: self._persist_state() def _current_history_file(self) -> Path: - return Path(self.state["current_history_file"]) + return self._current_history_file_for_user(self.cfg.allowed_username) - def _create_new_history_file(self, reason: str) -> Path: + def _history_dirs_for_user(self, username: str) -> tuple[Path, Path]: + uname = normalize_username(username) or "unknown" + history_dir = self.history_dir / uname + archive_dir = history_dir / "archive" + history_dir.mkdir(parents=True, exist_ok=True) + archive_dir.mkdir(parents=True, exist_ok=True) + return history_dir, archive_dir + + def _ensure_user_session(self, username: str) -> None: + uname = normalize_username(username) or self.cfg.allowed_username + sessions = self.state.setdefault("user_sessions", {}) + if not isinstance(sessions, dict): + sessions = {} + self.state["user_sessions"] = sessions + session = sessions.get(uname) + if isinstance(session, dict) and session.get("current_history_file"): + return + history_file = self._create_new_history_file("initial", uname) + sessions[uname] = {"current_history_file": str(history_file)} + if uname == self.cfg.allowed_username: + self.state["current_history_file"] = str(history_file) + self._persist_state() + + def _current_history_file_for_user(self, username: str) -> Path: + uname = normalize_username(username) or self.cfg.allowed_username + self._ensure_user_session(uname) + sessions = self.state.get("user_sessions") or {} + session = sessions.get(uname) or {} + return Path(session["current_history_file"]) + + def _create_new_history_file(self, reason: str, username: str) -> Path: ts = dt.datetime.now().strftime("%Y-%m-%d_%H%M%S") rnd = "".join(random.choices(string.hexdigits.lower(), k=8)) - path = self.history_dir / f"{ts}_{rnd}.jsonl" - JsonLineStore.append(path, {"ts": now_iso(), "type": "history_created", "reason": reason}) + history_dir, _ = self._history_dirs_for_user(username) + path = history_dir / f"{ts}_{rnd}.jsonl" + JsonLineStore.append(path, { + "ts": now_iso(), + "type": "history_created", + "reason": reason, + "username": normalize_username(username), + }) return path def _rotate_history(self, reason: str, username: str) -> Path: - current = self._current_history_file() + uname = normalize_username(username) or self.cfg.allowed_username + current = self._current_history_file_for_user(uname) + _, archive_dir = self._history_dirs_for_user(uname) if current.exists(): - archived = self.history_archive_dir / current.name + archived = archive_dir / current.name current.replace(archived) else: - archived = self.history_archive_dir / "(empty)" - new_file = self._create_new_history_file(reason) - self.state["current_history_file"] = str(new_file) + archived = archive_dir / "(empty)" + new_file = self._create_new_history_file(reason, uname) + sessions = self.state.setdefault("user_sessions", {}) + if not isinstance(sessions, dict): + sessions = {} + self.state["user_sessions"] = sessions + sessions[uname] = {"current_history_file": str(new_file)} + if uname == self.cfg.allowed_username: + self.state["current_history_file"] = str(new_file) self._persist_state() - self._append_history_event("history_rotated", {"reason": reason, "username": username, "archived": str(archived)}) + self._append_history_event("history_rotated", {"reason": reason, "username": uname, "archived": str(archived)}, username=uname) return archived def _append_history(self, history_path: Path, event_type: str, payload: dict[str, Any]) -> None: @@ -347,10 +488,28 @@ class ShinePyBotService: row.update(payload) JsonLineStore.append(history_path, row) - def _append_history_event(self, event_type: str, payload: dict[str, Any]) -> None: - history_path = self._current_history_file() + def _append_history_event(self, event_type: str, payload: dict[str, Any], username: str | None = None) -> None: + history_path = self._current_history_file_for_user(username or self.cfg.allowed_username) self._append_history(history_path, "system_event", {"event": event_type, **payload}) + def _send_player_welcome_once(self, chat_id: int, message_id: int, username: str) -> None: + uname = normalize_username(username) + sent = self.state.get("player_welcome_sent") + if not isinstance(sent, dict): + sent = {} + self.state["player_welcome_sent"] = sent + if sent.get(uname): + return + player_name = self._player_name(uname) + text = ( + f"Привет, {player_name}.\n" + "Можно задавать вопросы по проекту, просить анализ, идеи и подготовку готового ТЗ.\n" + "Команда /new начинает новую сессию и архивирует текущую историю." + ) + self._safe_send(chat_id, text, reply_to=message_id) + sent[uname] = now_iso() + self._persist_state() + def _resolve_chat_id(self, chat_id: int) -> int: migrations = self.state.get("chat_id_migrations") if not isinstance(migrations, dict): @@ -440,35 +599,39 @@ class ShinePyBotService: ) if is_channel_post and not is_allowed_channel: return + if chat_username and chat_username == self.cfg.allowed_channel_username: + self._remember_public_report_chat(chat_id) + + # Игнорируем системные сообщения о входе/выходе и смене заголовка/фото. + if message.get("new_chat_members") or message.get("left_chat_member"): + return + if message.get("group_chat_created") or message.get("supergroup_chat_created") or message.get("channel_chat_created"): + return text = (message.get("text") or message.get("caption") or "").strip() - history_path = self._current_history_file() - if author_username != self.cfg.allowed_username: - if is_channel_post or is_group_message: - self._append_history(history_path, "chat_context_message", { - "chatId": chat_id, - "messageId": message_id, - "updateType": update_type, - "chatType": chat_type, - "chatUsername": chat_username, - "chatTitle": chat_title, - "username": username, - "authorSignature": author_signature, - "text": text, - "hasVoice": bool(message.get("voice")), - "hasAudio": bool(message.get("audio")), - }) - if is_group_message: - self._safe_send(chat_id, "Получил сообщение.", reply_to=message_id) + actor_username = normalize_username(author_username) + is_allowed = self._is_allowed_user(actor_username) + is_private = chat_type == "private" + if not is_allowed: + if is_private: + self._safe_send(chat_id, "Извините, доступ к этому агенту пока не выдан. Обратитесь к Айдару.", reply_to=message_id) return + if self._is_allowed_player(actor_username) and not is_private: + return + + self._ensure_user_session(actor_username) + history_path = self._current_history_file_for_user(actor_username) + if self._is_allowed_player(actor_username): + self._send_player_welcome_once(chat_id, message_id, actor_username) if not text: if message.get("voice"): self._enqueue_voice_job( chat_id, message_id, - author_username, + actor_username, message["voice"].get("file_id"), + media_type="voice", update_type=update_type, chat_username=chat_username, chat_title=chat_title, @@ -480,8 +643,9 @@ class ShinePyBotService: self._enqueue_voice_job( chat_id, message_id, - author_username, + actor_username, message["audio"].get("file_id"), + media_type="audio", update_type=update_type, chat_username=chat_username, chat_title=chat_title, @@ -493,7 +657,7 @@ class ShinePyBotService: return if text.startswith("/"): - self._handle_command(chat_id, message_id, author_username, text) + self._handle_command(chat_id, message_id, actor_username, text) return self._append_history(history_path, "incoming_text", { @@ -503,11 +667,11 @@ class ShinePyBotService: "chatType": chat_type, "chatUsername": chat_username, "chatTitle": chat_title, - "username": author_username, + "username": actor_username, "authorSignature": author_signature, "text": text, }) - job = self._build_job_base(chat_id, message_id, author_username, str(history_path)) + job = self._build_job_base(chat_id, message_id, actor_username, str(history_path)) job["type"] = "text" job["text"] = text job["update_type"] = update_type @@ -515,6 +679,8 @@ class ShinePyBotService: job["chat_username"] = chat_username job["chat_title"] = chat_title job["author_signature"] = author_signature + job["role"] = "owner" if self._is_owner(actor_username) else "player" + job["player_name"] = self._player_name(actor_username) if job["role"] == "player" else "" with self.queue_lock: self.queue.append(job) self._persist_queue() @@ -527,6 +693,7 @@ class ShinePyBotService: username: str, file_id: str | None, *, + media_type: str = "voice", update_type: str = "message", chat_username: str = "", chat_title: str = "", @@ -536,7 +703,7 @@ class ShinePyBotService: if not file_id: self._safe_send(chat_id, "Не удалось прочитать file_id голосового.", reply_to=message_id) return - history_path = self._current_history_file() + history_path = self._current_history_file_for_user(username) self._append_history(history_path, "incoming_voice", { "chatId": chat_id, "messageId": message_id, @@ -547,15 +714,19 @@ class ShinePyBotService: "username": username, "authorSignature": author_signature, "fileId": file_id, + "mediaType": media_type, }) job = self._build_job_base(chat_id, message_id, username, str(history_path)) job["type"] = "voice" job["telegram_file_id"] = file_id + job["telegram_media_type"] = media_type job["update_type"] = update_type job["chat_type"] = chat_type job["chat_username"] = chat_username job["chat_title"] = chat_title job["author_signature"] = author_signature + job["role"] = "owner" if self._is_owner(username) else "player" + job["player_name"] = self._player_name(username) if job["role"] == "player" else "" with self.queue_lock: self.queue.append(job) self._persist_queue() @@ -579,8 +750,11 @@ class ShinePyBotService: "chat_username": "", "chat_title": "", "author_signature": "", + "role": "owner", + "player_name": "", "text": "", "telegram_file_id": "", + "telegram_media_type": "", "history_file": history_file, "attempts": 0, "retry_reason": "", @@ -592,8 +766,9 @@ class ShinePyBotService: def _handle_command(self, chat_id: int, message_id: int, username: str, text: str) -> None: lower = text.lower() + is_owner = self._is_owner(username) if lower in ("/start", "/help"): - self._safe_send(chat_id, self._help_text(), reply_to=message_id) + self._safe_send(chat_id, self._help_text(is_owner=is_owner), reply_to=message_id) return if lower == "/status": self._safe_send(chat_id, self._status_text(), reply_to=message_id) @@ -606,11 +781,14 @@ class ShinePyBotService: self._safe_send(chat_id, f"История очищена. Новый диалог начат.\nАрхив: {archived.name}", reply_to=message_id) return if lower in ("/restart_service", "/restart"): + if not is_owner: + self._safe_send(chat_id, "Команда недоступна.", reply_to=message_id) + return self._append_history_event("restart_service_requested", { "chatId": chat_id, "messageId": message_id, "username": username, - }) + }, username=username) self._safe_send( chat_id, "Перезапускаю сервис. Если задача была активна, после старта она вернётся в очередь и продолжится.", @@ -644,17 +822,19 @@ class ShinePyBotService: self._safe_send(chat_id, f"Задача удалена: {arg}" if cancelled else f"Задача не найдена: {arg}", reply_to=message_id) return - def _help_text(self) -> str: - return ( - "Доступные команды:\n" - "/status — активная задача и размер очереди\n" - "/queue — список задач в очереди\n" - "/stop — остановить текущую задачу\n" - "/cancel — удалить задачу по id (префикс) или все\n" - "/new — архивировать историю и начать новую\n" - "/restart_service — перезапустить сервис через systemd\n" - "/help — эта справка" - ) + def _help_text(self, *, is_owner: bool) -> str: + lines = [ + "Доступные команды:", + "/status — активная задача и размер очереди", + "/queue — список задач в очереди", + "/stop — остановить текущую задачу", + "/cancel — удалить задачу по id (префикс) или все", + "/new — архивировать историю и начать новую", + "/help — эта справка", + ] + if is_owner: + lines.insert(-1, "/restart_service — перезапустить сервис через systemd") + return "\n".join(lines) def _status_text(self) -> str: with self.queue_lock: @@ -768,6 +948,7 @@ class ShinePyBotService: self._safe_send(chat_id, f"Готово #{job_num}.", reply_to=message_id) self._append_history(history_path, "codex_response", {"jobId": job_id, "text": answer}) self._mark_job_done(job_id) + self._send_private_job_public_report(job, answer) except Exception as e: if self.stop_current_job: self._append_history(history_path, "job_stopped", {"jobId": job_id, "reason": str(e)}) @@ -775,6 +956,15 @@ class ShinePyBotService: self._mark_job_removed(job_id) self.stop_current_job = False return + if isinstance(e, VoiceTranscriptionError): + self._append_history(history_path, "voice_transcription_failed", { + "jobId": job_id, + "jobNum": job_num, + "stage": e.stage, + "retryable": e.retryable, + "error": e.user_message, + "detail": e.detail, + }) self._handle_job_failure(job, e) def _build_prompt(self, job: dict[str, Any]) -> str: @@ -782,6 +972,19 @@ class ShinePyBotService: retry_reason = (job.get("retry_reason") or "").strip() if retry_reason: retry_block = f"\n\nПометка retry: {retry_reason}" + role = (job.get("role") or "owner").strip().lower() + player_block = "" + if role == "player": + player_name = (job.get("player_name") or "").strip() + player_dir = self.cfg.codex_workdir / "Players" / (job.get("username") or "") + player_block = ( + "\n\nРежим игрока (обязательно):\n" + f"- Пользователь: {player_name} (@{job.get('username')}).\n" + f"- Рабочая папка игрока: {player_dir}\n" + "- Код проекта не изменять.\n" + "- Можно отвечать на вопросы по проекту, предлагать идеи и готовить ТЗ.\n" + "- Если нужны правки кода, описывать предложение текстом и сохранять материалы только в папке игрока." + ) return ( "Пришло сообщение в Telegram.\n" f"Тип: {job.get('type')}\n" @@ -794,7 +997,7 @@ class ShinePyBotService: f"{job.get('text')}\n\n" f"История диалога (JSONL): {job.get('history_file')}\n" f"Инструкции агента: {self.cfg.agent_instructions_file}\n" - f"Работай в рабочем проекте аккуратно и верни только текст ответа пользователю.{retry_block}" + f"Работай в рабочем проекте аккуратно и верни только текст ответа пользователю.{player_block}{retry_block}" ) def _run_codex(self, prompt: str, chat_id: int, message_id: int, job_id: str, job_num: Any) -> str: @@ -921,7 +1124,11 @@ class ShinePyBotService: chat_id = int(job["chat_id"]) message_id = int(job["message_id"]) error_text = str(err).strip() or err.__class__.__name__ - print(f"[py-bot] Ошибка job={job_id[:8]}: {error_text}", flush=True) + user_error_text = self._user_error_text(err) + retryable = not isinstance(err, VoiceTranscriptionError) or err.retryable + log_error_text = err.log_text() if isinstance(err, VoiceTranscriptionError) else error_text + print(f"[py-bot] Ошибка job={job_id[:8]}: {log_error_text}", flush=True) + print(traceback.format_exc(), flush=True) with self.queue_lock: target = next((j for j in self.queue if j.get("id") == job_id), None) @@ -931,7 +1138,7 @@ class ShinePyBotService: target["attempts"] = attempts target["last_error"] = error_text[:1000] target["updated_at"] = now_iso() - if attempts < self.cfg.max_retries: + if retryable and attempts < self.cfg.max_retries: target["status"] = "pending" target["retry_reason"] = error_text[:200] self._persist_queue() @@ -942,9 +1149,19 @@ class ShinePyBotService: will_retry = False if will_retry: - self._safe_send(chat_id, f"Ошибка задачи #{job_num}, повтор: {attempts}/{self.cfg.max_retries}", reply_to=message_id) + self._safe_send( + chat_id, + f"{user_error_text}\nПовторю задачу #{job_num}: попытка {attempts + 1}/{self.cfg.max_retries}.", + reply_to=message_id, + ) else: - self._safe_send(chat_id, f"Ошибка задачи #{job_num}. Лимит попыток исчерпан.", reply_to=message_id) + self._safe_send(chat_id, f"{user_error_text}\nЗадача #{job_num} остановлена.", reply_to=message_id) + + def _user_error_text(self, err: Exception) -> str: + if isinstance(err, VoiceTranscriptionError): + return f"Не удалось распознать голосовое: {err.user_message}" + error_text = str(err).strip() or err.__class__.__name__ + return f"Ошибка выполнения задачи: {error_text}" def _mark_job_done(self, job_id: str) -> None: with self.queue_lock: @@ -956,27 +1173,145 @@ class ShinePyBotService: self.queue = [j for j in self.queue if j.get("id") != job_id] self._persist_queue() - def _safe_send(self, chat_id: int, text: str, reply_to: int | None = None) -> None: - text = (text or "").strip() - if not text: + def _remember_public_report_chat(self, chat_id: int) -> None: + if self.state.get("public_report_chat_id") == chat_id: return - if len(text) > 3900: - text = text[:3900] + "\n...[обрезано]" - resolved_chat_id = self._resolve_chat_id(chat_id) - resolved_reply_to = reply_to if resolved_chat_id == chat_id else None + self.state["public_report_chat_id"] = chat_id + self.state["updated_at"] = now_iso() + self._persist_state() + + def _public_report_chat_id(self) -> int | str | None: + chat_id = self.state.get("public_report_chat_id") + if isinstance(chat_id, int): + return self._resolve_chat_id(chat_id) + if self.cfg.allowed_channel_username: + return f"@{self.cfg.allowed_channel_username}" + return None + + def _send_private_job_public_report(self, job: dict[str, Any], answer: str) -> None: + if job.get("chat_type") != "private": + return + report_chat_id = self._public_report_chat_id() + if report_chat_id is None: + return + + job_num = job.get("num", "?") + source_text = (job.get("text") or "").strip() + if not source_text: + source_text = "(пустой текст запроса)" + role = (job.get("role") or "owner").strip().lower() + author_label = "Айдар" + if role == "player": + player_name = (job.get("player_name") or "").strip() or job.get("username") or "Игрок" + author_label = f"{player_name} (@{job.get('username')})" + if job.get("type") == "voice": + voice_file_id = (job.get("telegram_file_id") or "").strip() + media_type = (job.get("telegram_media_type") or "voice").strip() + request_caption = self._trim_telegram_caption( + f"{author_label} сделал {media_type}-запрос, задача #{job_num}.\n\n" + f"Распознанный текст:\n{source_text}" + ) + request_message_id = None + if voice_file_id: + request_message_id = self._safe_send_telegram_file( + report_chat_id, + voice_file_id, + media_type=media_type, + caption=request_caption, + ) + if request_message_id is None: + request_message_id = self._safe_send(report_chat_id, request_caption) + else: + request_report = ( + f"{author_label} сделал запрос, задача #{job_num}.\n\n" + f"{source_text}" + ) + request_message_id = self._safe_send(report_chat_id, request_report) + if request_message_id is None: + return + + answer_text = (answer or "").strip() or "(пустой ответ)" + answer_chunks = split_long_text(f"Ответ на задачу #{job_num}:\n\n{answer_text}") + for chunk in answer_chunks: + self._safe_send(report_chat_id, chunk, reply_to=request_message_id) + + @staticmethod + def _trim_telegram_caption(text: str, limit: int = 1000) -> str: + text = (text or "").strip() + if len(text) <= limit: + return text + return text[:limit].rstrip() + "\n...[обрезано]" + + def _safe_send_telegram_file( + self, + chat_id: int | str, + file_id: str, + *, + media_type: str = "voice", + caption: str = "", + reply_to: int | None = None, + ) -> int | None: + file_id = (file_id or "").strip() + if not file_id: + return None + caption = self._trim_telegram_caption(caption) + resolved_chat_id: int | str = self._resolve_chat_id(chat_id) if isinstance(chat_id, int) else chat_id + resolved_reply_to = reply_to if resolved_chat_id == chat_id or isinstance(chat_id, str) else None + + def send(target_chat_id: int | str, target_reply_to: int | None) -> dict[str, Any]: + if media_type == "audio": + return self.telegram.send_audio(target_chat_id, file_id, caption=caption, reply_to_message_id=target_reply_to) + return self.telegram.send_voice(target_chat_id, file_id, caption=caption, reply_to_message_id=target_reply_to) + try: - self.telegram.send_message(resolved_chat_id, text, reply_to_message_id=resolved_reply_to) + sent = send(resolved_chat_id, resolved_reply_to) + result = sent.get("result") or {} + message_id = result.get("message_id") + return message_id if isinstance(message_id, int) else None except Exception as e: migrate_to_chat_id = self._extract_migrate_to_chat_id(str(e)) if migrate_to_chat_id is not None: - self._remember_chat_migration(resolved_chat_id, migrate_to_chat_id, "send_message_error") + if isinstance(resolved_chat_id, int): + self._remember_chat_migration(resolved_chat_id, migrate_to_chat_id, "send_file_error") try: - self.telegram.send_message(migrate_to_chat_id, text, reply_to_message_id=None) - return + sent = send(migrate_to_chat_id, None) + result = sent.get("result") or {} + message_id = result.get("message_id") + return message_id if isinstance(message_id, int) else None + except Exception as retry_error: + print(f"[py-bot] sendFile retry after migration error: {retry_error}", flush=True) + return None + print(f"[py-bot] sendFile error: {e}", flush=True) + return None + + def _safe_send(self, chat_id: int | str, text: str, reply_to: int | None = None) -> int | None: + text = (text or "").strip() + if not text: + return None + if len(text) > 3900: + text = text[:3900] + "\n...[обрезано]" + resolved_chat_id: int | str = self._resolve_chat_id(chat_id) if isinstance(chat_id, int) else chat_id + resolved_reply_to = reply_to if resolved_chat_id == chat_id or isinstance(chat_id, str) else None + try: + sent = self.telegram.send_message(resolved_chat_id, text, reply_to_message_id=resolved_reply_to) + result = sent.get("result") or {} + message_id = result.get("message_id") + return message_id if isinstance(message_id, int) else None + except Exception as e: + migrate_to_chat_id = self._extract_migrate_to_chat_id(str(e)) + if migrate_to_chat_id is not None: + if isinstance(resolved_chat_id, int): + self._remember_chat_migration(resolved_chat_id, migrate_to_chat_id, "send_message_error") + try: + sent = self.telegram.send_message(migrate_to_chat_id, text, reply_to_message_id=None) + result = sent.get("result") or {} + message_id = result.get("message_id") + return message_id if isinstance(message_id, int) else None except Exception as retry_error: print(f"[py-bot] sendMessage retry after migration error: {retry_error}", flush=True) - return + return None print(f"[py-bot] sendMessage error: {e}", flush=True) + return None def _schedule_self_restart(self) -> None: if self.restart_requested: @@ -992,26 +1327,94 @@ class ShinePyBotService: def _transcribe_voice_job(self, job: dict[str, Any]) -> str: if not self.cfg.openai_api_key: - raise RuntimeError("Не задан OPENAI_API_KEY для распознавания voice") + raise VoiceTranscriptionError( + "не настроен ключ OpenAI для распознавания.", + stage="config", + retryable=False, + ) file_id = (job.get("telegram_file_id") or "").strip() if not file_id: - raise RuntimeError("Пустой telegram_file_id") + raise VoiceTranscriptionError( + "Telegram не передал идентификатор файла.", + stage="telegram_file_id", + retryable=False, + ) + job_id = str(job.get("id") or "")[:8] + job_num = job.get("num", "?") + media_type = (job.get("telegram_media_type") or "voice").strip() + started_at = time.time() + print(f"[py-bot] transcribe start job={job_id} num={job_num} media={media_type}", flush=True) file_bytes, filename = self._download_telegram_file(file_id) + print( + f"[py-bot] transcribe downloaded job={job_id} filename={filename} size={len(file_bytes)} bytes", + flush=True, + ) text = self._openai_transcribe(file_bytes, filename).strip() if not text: - raise RuntimeError("Распознавание вернуло пустой текст") + raise VoiceTranscriptionError( + "сервис распознавания вернул пустой текст. Возможно, в записи нет слышимой речи или качество звука слишком низкое.", + stage="empty_text", + retryable=False, + ) + elapsed = self._format_duration(int(time.time() - started_at)) + print(f"[py-bot] transcribe done job={job_id} chars={len(text)} elapsed={elapsed}", flush=True) return text def _download_telegram_file(self, file_id: str) -> tuple[bytes, str]: - result = self.telegram.call("getFile", {"file_id": file_id}, timeout=60) + try: + result = self.telegram.call("getFile", {"file_id": file_id}, timeout=120) + except TimeoutError as e: + raise VoiceTranscriptionError( + "Telegram долго не отдавал информацию о файле.", + stage="telegram_get_file_timeout", + detail=str(e), + ) from e + except Exception as e: + raise VoiceTranscriptionError( + "не удалось получить информацию о файле из Telegram.", + stage="telegram_get_file", + detail=str(e), + ) from e info = result.get("result") or {} file_path = info.get("file_path") if not file_path: - raise RuntimeError("Telegram getFile не вернул file_path") + raise VoiceTranscriptionError( + "Telegram не вернул путь к файлу.", + stage="telegram_file_path", + retryable=True, + detail=json.dumps(info, ensure_ascii=False)[:1000], + ) file_url = f"https://api.telegram.org/file/bot{self.cfg.telegram_bot_token}/{file_path}" req = request.Request(file_url, method="GET") - with request.urlopen(req, timeout=120) as resp: - data = resp.read() + try: + with request.urlopen(req, timeout=self.cfg.telegram_file_download_timeout_seconds) as resp: + data = resp.read() + except TimeoutError as e: + raise VoiceTranscriptionError( + f"Telegram не успел отдать аудиофайл за {self.cfg.telegram_file_download_timeout_seconds} секунд.", + stage="telegram_download_timeout", + detail=str(e), + ) from e + except error.HTTPError as e: + detail = e.read().decode("utf-8", errors="replace") + raise VoiceTranscriptionError( + f"Telegram вернул ошибку HTTP {e.code} при скачивании аудио.", + stage="telegram_download_http", + retryable=e.code >= 500 or e.code == 429, + detail=detail[:1000], + ) from e + except error.URLError as e: + raise VoiceTranscriptionError( + "не удалось скачать аудиофайл из Telegram из-за сетевой ошибки.", + stage="telegram_download_network", + detail=str(e.reason), + ) from e + if not data: + raise VoiceTranscriptionError( + "Telegram отдал пустой аудиофайл.", + stage="telegram_download_empty", + retryable=True, + ) original_name = Path(file_path).name or "audio.ogg" lower = original_name.lower() # OpenAI transcription может не принимать расширение .oga, нормализуем в .ogg. @@ -1051,11 +1454,40 @@ class ShinePyBotService: req.add_header("Authorization", f"Bearer {self.cfg.openai_api_key}") req.add_header("Content-Type", f"multipart/form-data; boundary={boundary}") try: - with request.urlopen(req, timeout=240) as resp: + with request.urlopen(req, timeout=self.cfg.openai_transcribe_timeout_seconds) as resp: return resp.read().decode("utf-8", errors="replace") + except TimeoutError as e: + raise VoiceTranscriptionError( + f"OpenAI не успел распознать аудио за {self.cfg.openai_transcribe_timeout_seconds} секунд.", + stage="openai_transcribe_timeout", + detail=str(e), + ) from e except error.HTTPError as e: detail = e.read().decode("utf-8", errors="replace") - raise RuntimeError(f"OpenAI transcribe HTTP {e.code}: {detail}") from e + if e.code == 400: + user_message = "OpenAI не принял аудиофайл для распознавания." + elif e.code == 401: + user_message = "OpenAI отклонил ключ API для распознавания." + elif e.code == 413: + user_message = "аудиофайл слишком большой для распознавания OpenAI." + elif e.code == 429: + user_message = "OpenAI временно ограничил распознавание из-за лимита запросов." + elif e.code >= 500: + user_message = "OpenAI временно не смог обработать распознавание." + else: + user_message = f"OpenAI вернул ошибку HTTP {e.code} при распознавании." + raise VoiceTranscriptionError( + user_message, + stage="openai_transcribe_http", + retryable=e.code == 429 or e.code >= 500, + detail=detail[:1500], + ) from e + except error.URLError as e: + raise VoiceTranscriptionError( + "не удалось отправить аудио в OpenAI из-за сетевой ошибки.", + stage="openai_transcribe_network", + detail=str(e.reason), + ) from e @staticmethod def _extract_codex_user_note(line: str) -> str | None: diff --git a/shine-UI/js/app.js b/shine-UI/js/app.js index 1f48cba..2cb4931 100644 --- a/shine-UI/js/app.js +++ b/shine-UI/js/app.js @@ -59,6 +59,7 @@ import * as deviceSessionView from './pages/device-session-view.js'; import * as languageView from './pages/language-view.js'; import * as appLogView from './pages/app-log-view.js'; import * as pwaDiagnosticsView from './pages/pwa-diagnostics-view.js'; +import * as solanaUsersInitView from './pages/solana-users-init-view.js'; import * as messagesList from './pages/messages-list.js'; import * as contactSearchView from './pages/contact-search-view.js'; import * as chatView from './pages/chat-view.js'; @@ -98,6 +99,7 @@ const routes = { 'language-view': languageView, 'app-log-view': appLogView, 'pwa-diagnostics-view': pwaDiagnosticsView, + 'solana-users-init-view': solanaUsersInitView, 'messages-list': messagesList, 'contact-search-view': contactSearchView, 'chat-view': chatView, diff --git a/shine-UI/js/pages/developer-settings-view.js b/shine-UI/js/pages/developer-settings-view.js index 7ea90ef..d7b6d7b 100644 --- a/shine-UI/js/pages/developer-settings-view.js +++ b/shine-UI/js/pages/developer-settings-view.js @@ -262,6 +262,7 @@ export function render({ navigate }) { + @@ -275,8 +276,10 @@ export function render({ navigate }) { const forceUpdateBtn = card.querySelector('#settings-force-ui-update'); const forceUpdateHelpBtn = card.querySelector('#settings-force-update-help'); const uiErrorReportingBtn = card.querySelector('#settings-ui-error-reporting'); + const solanaUsersInitBtn = card.querySelector('#settings-solana-users-init'); appLogBtn?.addEventListener('click', () => navigate('app-log-view')); + solanaUsersInitBtn?.addEventListener('click', () => navigate('solana-users-init-view')); diagnosticsBtn?.addEventListener('click', () => navigate('pwa-diagnostics-view')); uploadAvatarBtn?.addEventListener('click', () => { openDeveloperAvatarUploadModal({ diff --git a/shine-UI/js/pages/solana-users-init-view.js b/shine-UI/js/pages/solana-users-init-view.js new file mode 100644 index 0000000..062ad15 --- /dev/null +++ b/shine-UI/js/pages/solana-users-init-view.js @@ -0,0 +1,196 @@ +import { renderHeader } from '../components/header.js'; +import { + SHINE_USERS_ECONOMY_CONFIG_SEED, + SHINE_USERS_PROGRAM_ID, + SOLANA_CLUSTER, +} from '../solana-programs.js'; +import { state } from '../state.js'; + +export const pageMeta = { id: 'solana-users-init-view', title: 'Solana Init (users)' }; + +let solanaLibPromise = null; +function loadSolanaLib() { + if (!solanaLibPromise) { + solanaLibPromise = import('https://esm.sh/@solana/web3.js@1.98.4?bundle'); + } + return solanaLibPromise; +} + +function getProvider() { + const p = globalThis?.solana; + if (!p || !p.isPhantom) return null; + return p; +} + +function shortAddr(value = '') { + const v = String(value || '').trim(); + if (v.length < 12) return v; + return `${v.slice(0, 6)}...${v.slice(-6)}`; +} + +export function render({ navigate }) { + const screen = document.createElement('section'); + screen.className = 'stack'; + + const card = document.createElement('div'); + card.className = 'card stack'; + + const status = document.createElement('p'); + status.className = 'meta-muted'; + status.textContent = 'Подключите кошелёк и выполните init_users_economy_config.'; + + const programId = SHINE_USERS_PROGRAM_ID; + const programInput = document.createElement('input'); + programInput.className = 'input'; + programInput.type = 'text'; + programInput.readOnly = true; + programInput.value = programId; + + const rpcInput = document.createElement('input'); + rpcInput.className = 'input'; + rpcInput.type = 'text'; + rpcInput.readOnly = true; + rpcInput.value = String(state.entrySettings.solanaServer || ''); + + const walletLine = document.createElement('p'); + walletLine.className = 'meta-muted'; + walletLine.textContent = 'Кошелёк: не подключен'; + + const economyPdaLine = document.createElement('p'); + economyPdaLine.className = 'meta-muted'; + economyPdaLine.textContent = 'PDA economy config: —'; + + const txLine = document.createElement('p'); + txLine.className = 'meta-muted'; + txLine.textContent = 'TX: —'; + + const connectBtn = document.createElement('button'); + connectBtn.className = 'text-btn'; + connectBtn.type = 'button'; + connectBtn.textContent = 'Подключить кошелёк'; + + const initBtn = document.createElement('button'); + initBtn.className = 'primary-btn'; + initBtn.type = 'button'; + initBtn.textContent = 'Запустить init_users_economy_config'; + initBtn.disabled = true; + + let provider = null; + let walletPubkey = null; + let economyPda = null; + + async function recomputePda() { + const solana = await loadSolanaLib(); + const pid = new solana.PublicKey(programId); + const [pda] = solana.PublicKey.findProgramAddressSync( + [new TextEncoder().encode(SHINE_USERS_ECONOMY_CONFIG_SEED)], + pid, + ); + economyPda = pda; + economyPdaLine.textContent = `PDA economy config: ${pda.toBase58()}`; + } + + connectBtn.addEventListener('click', async () => { + status.textContent = 'Подключение кошелька...'; + try { + provider = getProvider(); + if (!provider) throw new Error('Phantom не найден'); + const result = await provider.connect(); + walletPubkey = result?.publicKey || provider.publicKey; + if (!walletPubkey) throw new Error('Кошелёк не вернул public key'); + walletLine.textContent = `Кошелёк: ${walletPubkey.toBase58()} (${shortAddr(walletPubkey.toBase58())})`; + initBtn.disabled = false; + status.textContent = 'Кошелёк подключен.'; + } catch (e) { + status.textContent = `Ошибка подключения: ${e?.message || 'unknown'}`; + } + }); + + initBtn.addEventListener('click', async () => { + if (!provider || !walletPubkey || !economyPda) return; + initBtn.disabled = true; + status.textContent = 'Отправка транзакции...'; + txLine.textContent = 'TX: —'; + try { + const solana = await loadSolanaLib(); + const connection = new solana.Connection(String(state.entrySettings.solanaServer || ''), 'confirmed'); + const programPubkey = new solana.PublicKey(programId); + + const discriminator = Uint8Array.from([13, 16, 103, 175, 121, 137, 166, 222]); + const ix = new solana.TransactionInstruction({ + programId: programPubkey, + keys: [ + { pubkey: walletPubkey, isSigner: true, isWritable: true }, + { pubkey: economyPda, isSigner: false, isWritable: true }, + { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false }, + ], + data: discriminator, + }); + + const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed'); + const tx = new solana.Transaction({ + feePayer: walletPubkey, + blockhash, + lastValidBlockHeight, + }).add(ix); + + const signed = await provider.signTransaction(tx); + const sig = await connection.sendRawTransaction(signed.serialize(), { skipPreflight: false }); + await connection.confirmTransaction({ signature: sig, blockhash, lastValidBlockHeight }, 'confirmed'); + + txLine.textContent = `TX: ${sig}`; + status.textContent = 'Успешно: init_users_economy_config выполнен.'; + } catch (e) { + const message = String(e?.message || 'unknown'); + txLine.textContent = 'TX: ошибка'; + if (message.toLowerCase().includes('already') || message.includes('1000')) { + status.textContent = 'PDA уже инициализирован. Повторный init не требуется.'; + } else { + status.textContent = `Ошибка init: ${message}`; + } + } finally { + initBtn.disabled = false; + } + }); + + void recomputePda(); + + card.append( + (() => { + const t = document.createElement('p'); + t.className = 'meta-muted'; + t.textContent = `Cluster: ${SOLANA_CLUSTER}`; + return t; + })(), + (() => { + const label = document.createElement('label'); + label.className = 'field-label'; + label.textContent = 'Program ID (shine_users)'; + return label; + })(), + programInput, + (() => { + const label = document.createElement('label'); + label.className = 'field-label'; + label.textContent = 'RPC endpoint'; + return label; + })(), + rpcInput, + walletLine, + economyPdaLine, + txLine, + connectBtn, + initBtn, + status, + ); + + screen.append( + renderHeader({ + title: 'Solana Init (users)', + leftAction: { label: '←', onClick: () => navigate('developer-settings-view') }, + }), + card, + ); + + return screen; +} diff --git a/shine-UI/js/router.js b/shine-UI/js/router.js index b9f5d61..bb4351a 100644 --- a/shine-UI/js/router.js +++ b/shine-UI/js/router.js @@ -182,7 +182,8 @@ export function resolveToolbarActive(pageId) { pageId === 'device-session-view' || pageId === 'language-view' || pageId === 'app-log-view' || - pageId === 'pwa-diagnostics-view' + pageId === 'pwa-diagnostics-view' || + pageId === 'solana-users-init-view' ) return 'profile-view'; if (pageId === 'chat-view' || pageId === 'contact-search-view') return 'messages-list'; if (pageId === 'channel-view' || pageId === 'channel-thread-view' || pageId === 'add-channel-view' || pageId === 'add-personal-public-chat-view') return 'channels-list'; diff --git a/shine-UI/js/services/solana-wallet-service.js b/shine-UI/js/services/solana-wallet-service.js index 8b5540d..c91345d 100644 --- a/shine-UI/js/services/solana-wallet-service.js +++ b/shine-UI/js/services/solana-wallet-service.js @@ -1,8 +1,9 @@ import { deriveEd25519FromPassword } from './crypto-utils.js'; import { extractDeviceKey32FromStoredValue } from './device-key-utils.js'; import { loadEncryptedUserSecrets } from './key-vault.js'; +import { SOLANA_ENDPOINT_DEFAULT } from '../solana-programs.js'; -const DEFAULT_SOLANA_ENDPOINT = 'https://api.devnet.solana.com'; +const DEFAULT_SOLANA_ENDPOINT = SOLANA_ENDPOINT_DEFAULT; const TOPUP_SITE_URL = 'https://shine-promo-solana-devnet.shineup.me/'; let solanaLibPromise = null; diff --git a/shine-UI/js/solana-programs.js b/shine-UI/js/solana-programs.js new file mode 100644 index 0000000..8c84213 --- /dev/null +++ b/shine-UI/js/solana-programs.js @@ -0,0 +1,8 @@ +export const SOLANA_CLUSTER = 'devnet'; +export const SOLANA_ENDPOINT_DEFAULT = 'https://api.devnet.solana.com'; + +// Программа регистрации пользователей SHiNE (shine_users), задеплоена в devnet. +export const SHINE_USERS_PROGRAM_ID = 'FZS1YctoeEhCkZ5VTjsysUFAXR8CqxYztcLboXcg2Rpm'; +export const SHINE_USERS_ECONOMY_CONFIG_SEED = 'shine_users_economy_config'; +export const SHINE_LOGIN_GUARD_PROGRAM_ID = '3xkopA7cXagxzMFrKdv3NCBfV6BKiRJCk69kr27M2sRo'; +export const SHINE_PAYMENTS_PROGRAM_ID = 'm48pWRGWrMj3TEHjuU4zsp5Gju4e7ZaPovk8RcVt7kR'; diff --git a/shine-UI/js/state.js b/shine-UI/js/state.js index 9e5245e..6fcbadb 100644 --- a/shine-UI/js/state.js +++ b/shine-UI/js/state.js @@ -1,5 +1,6 @@ import { AuthService } from './services/auth-service.js'; import { listStoredMessages, putStoredMessage } from './services/message-store.js'; +import { SOLANA_ENDPOINT_DEFAULT } from './solana-programs.js'; const clone = (value) => JSON.parse(JSON.stringify(value)); const SESSION_STORAGE_KEY = 'shine-ui-current-session-v1'; @@ -76,7 +77,7 @@ function inferTunnelWsUrl() { } const LOCAL_WS_OVERRIDE_URL = readLocalWsOverrideUrl() || inferTunnelWsUrl(); -const DEFAULT_SOLANA_SERVER = 'https://api.devnet.solana.com'; +const DEFAULT_SOLANA_SERVER = SOLANA_ENDPOINT_DEFAULT; const DEFAULT_SHINE_SERVER = 'wss://shineup.me/ws'; const DEFAULT_ARWEAVE_SERVER = 'https://arweave.net'; const DEFAULT_CALL_PREFLIGHT_TIMEOUT_MS = 6000; diff --git a/shine-server-config/src/main/java/utils/config/SolanaProgramsConfig.java b/shine-server-config/src/main/java/utils/config/SolanaProgramsConfig.java new file mode 100644 index 0000000..f238da6 --- /dev/null +++ b/shine-server-config/src/main/java/utils/config/SolanaProgramsConfig.java @@ -0,0 +1,21 @@ +package utils.config; + +/** + * Публичные адреса Solana-программ SHiNE (жёстко зафиксированы для devnet). + * Секреты на сервере не хранятся. + */ +public final class SolanaProgramsConfig { + + private SolanaProgramsConfig() {} + + public static final String SOLANA_CLUSTER = "devnet"; + public static final String SOLANA_RPC_URL = "https://api.devnet.solana.com"; + + // Программа регистрации пользователей (shine_users), задеплоена в devnet. + public static final String SHINE_USERS_PROGRAM_ID = "FZS1YctoeEhCkZ5VTjsysUFAXR8CqxYztcLboXcg2Rpm"; + + // Отдельно фиксируем адреса связанной инфраструктуры, чтобы UI/сервер ссылались одинаково. + public static final String SHINE_LOGIN_GUARD_PROGRAM_ID = "3xkopA7cXagxzMFrKdv3NCBfV6BKiRJCk69kr27M2sRo"; + public static final String SHINE_PAYMENTS_PROGRAM_ID = "m48pWRGWrMj3TEHjuU4zsp5Gju4e7ZaPovk8RcVt7kR"; +} + diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/channels/Net_GetMessageThread_Handler.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/channels/Net_GetMessageThread_Handler.java index 066bd86..7ee1ee5 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/channels/Net_GetMessageThread_Handler.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/channels/Net_GetMessageThread_Handler.java @@ -18,6 +18,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; +import java.util.Base64; import java.util.List; public class Net_GetMessageThread_Handler implements JsonMessageHandler { @@ -182,6 +183,10 @@ public class Net_GetMessageThread_Handler implements JsonMessageHandler { node.setVersionsTotal(versions.size()); node.setText(versions.get(versions.size() - 1).getText()); + if (row.blockBytes != null) { + node.setRawBlockB64(Base64.getEncoder().encodeToString(row.blockBytes)); + } + int[] stats = ChannelsReadSupport.loadStats(c, row.bchName, row.blockNumber, row.blockHash); node.setLikesCount(stats[0]); node.setRepliesCount(stats[1]); diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/channels/entyties/Net_GetMessageThread_Response.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/channels/entyties/Net_GetMessageThread_Response.java index 963aff1..7a9f37f 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/channels/entyties/Net_GetMessageThread_Response.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/channels/entyties/Net_GetMessageThread_Response.java @@ -21,9 +21,13 @@ public class Net_GetMessageThread_Response extends Net_Response { public static class MessageNode extends Net_GetChannelMessages_Response.MessageItem { private ChannelInfo channelInfo; + private String rawBlockB64; public ChannelInfo getChannelInfo() { return channelInfo; } public void setChannelInfo(ChannelInfo channelInfo) { this.channelInfo = channelInfo; } + + public String getRawBlockB64() { return rawBlockB64; } + public void setRawBlockB64(String rawBlockB64) { this.rawBlockB64 = rawBlockB64; } } public static class ChannelInfo { diff --git a/shine-solana/shine/doc/SHiNE-user-format-v.1.0.md b/shine-solana/shine/doc/SHiNE-user-format-v.1.0.md index 299b098..036c130 100644 --- a/shine-solana/shine/doc/SHiNE-user-format-v.1.0.md +++ b/shine-solana/shine/doc/SHiNE-user-format-v.1.0.md @@ -51,7 +51,7 @@ | N | Поле | Тип | Размер | Правило | |---|------|-----|--------|---------| | 1 | `magic` | bytes | 5 | Всегда `SHiNE`. | -| 2 | `format_major` | `u8` | 1 | Для нового формата: `2`. | +| 2 | `format_major` | `u8` | 1 | Для первого формата: `1`. | | 3 | `format_minor` | `u8` | 1 | Для первой версии нового формата: `0`. | | 4 | `record_len` | `u16` | 2 | Длина полезной записи от `magic` до `signature` включительно, без padding. | | 5 | `created_at_ms` | `u64` | 8 | Время создания записи, Unix time в миллисекундах. Не меняется. | @@ -63,7 +63,7 @@ После первых 9 полей идет набор типизированных блоков: ```text -UserPdaRecordV2 +UserPdaRecordV1 - fixed_header: поля 1..9 - blocks_count: u8 - blocks: TypedBlock[blocks_count] @@ -89,7 +89,7 @@ UserPdaRecordV2 Правила: -- неизвестный `block_type` в `format_major = 2` считается ошибкой; +- неизвестный `block_type` в `format_major = 1` считается ошибкой; - обязательные блоки: `RootKeyBlock`, `DeviceKeyBlock`, `BlockchainRegistryBlock`; - необязательные блоки: `ServerProfileBlock`, `AccessServersBlock`, `TrustedStateBlock`; - каждый обязательный блок должен встречаться ровно один раз; diff --git a/shine-solana/shine/programs/shine_users/src/users.rs b/shine-solana/shine/programs/shine_users/src/users.rs index 7055f79..7a30cfe 100644 --- a/shine-solana/shine/programs/shine_users/src/users.rs +++ b/shine-solana/shine/programs/shine_users/src/users.rs @@ -12,7 +12,7 @@ use common::utils::{create_pda, safe_read_pda, write_to_pda, ErrCode}; use std::str::FromStr; const MAGIC: &[u8; 5] = b"SHiNE"; -const FORMAT_MAJOR: u8 = 2; +const FORMAT_MAJOR: u8 = 1; const FORMAT_MINOR: u8 = 0; const MAX_SYNC_SERVERS: usize = 32; const MAX_AUTO_REALLOC_INCREASE: usize = 10_000; diff --git a/shine-solana/shine/tests/shine.ts b/shine-solana/shine/tests/shine.ts index 1a1b82e..6b3ea82 100644 --- a/shine-solana/shine/tests/shine.ts +++ b/shine-solana/shine/tests/shine.ts @@ -11,7 +11,7 @@ import { expect } from "chai"; import { Shine } from "../target/types/shine"; const MAGIC = Buffer.from("SHiNE", "utf8"); -const FORMAT_MAJOR = 2; +const FORMAT_MAJOR = 1; const FORMAT_MINOR = 0; const ZERO_HASH = Buffer.alloc(32, 0); const LAST_BLOCK_STATE_PREFIX = Buffer.from("SHiNE_LAST_BLOCK", "utf8");