hermes-vk-community 1.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hermes_vk_community-1.0.2/.gitignore +15 -0
- hermes_vk_community-1.0.2/PKG-INFO +233 -0
- hermes_vk_community-1.0.2/README.md +214 -0
- hermes_vk_community-1.0.2/docs/vk-rich-text-compatibility.md +77 -0
- hermes_vk_community-1.0.2/plugin.yaml +13 -0
- hermes_vk_community-1.0.2/pyproject.toml +33 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/__init__.py +3 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/adapter.py +1449 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/capabilities.py +35 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/cli.py +465 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/client.py +244 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/compat.py +137 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/config.py +173 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/data/vk-capabilities.json +36 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/errors.py +28 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/models.py +240 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/plugin.py +57 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/renderer.py +654 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/security.py +119 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/setup.py +248 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/storage.py +546 -0
- hermes_vk_community-1.0.2/src/hermes_vk_community/table_image.py +187 -0
- hermes_vk_community-1.0.2/tests/__init__.py +0 -0
- hermes_vk_community-1.0.2/tests/fixtures/vk/formatting/capability-profile.json +36 -0
- hermes_vk_community-1.0.2/tests/fixtures/vk/formatting/live-probe-2026-07-15.json +125 -0
- hermes_vk_community-1.0.2/tests/fixtures/vk/formatting/live-probe-format-data-2026-07-15.json +384 -0
- hermes_vk_community-1.0.2/tests/test_adapter.py +552 -0
- hermes_vk_community-1.0.2/tests/test_cli.py +26 -0
- hermes_vk_community-1.0.2/tests/test_client.py +127 -0
- hermes_vk_community-1.0.2/tests/test_config.py +76 -0
- hermes_vk_community-1.0.2/tests/test_plugin.py +76 -0
- hermes_vk_community-1.0.2/tests/test_renderer.py +171 -0
- hermes_vk_community-1.0.2/tests/test_security.py +84 -0
- hermes_vk_community-1.0.2/tests/test_setup.py +156 -0
- hermes_vk_community-1.0.2/tests/test_storage.py +197 -0
- hermes_vk_community-1.0.2/tests/test_table_image.py +22 -0
- hermes_vk_community-1.0.2/tests/test_tls_transport.py +157 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hermes-vk-community
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: VK Community Long Poll platform plugin for Hermes Agent
|
|
5
|
+
Author: Hermes VK Community contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: <3.14,>=3.11
|
|
8
|
+
Requires-Dist: aiohttp>=3.14.1
|
|
9
|
+
Requires-Dist: aiosqlite==0.22.1
|
|
10
|
+
Requires-Dist: filetype==1.2.0
|
|
11
|
+
Requires-Dist: hermes-agent>=0.18.2
|
|
12
|
+
Requires-Dist: markdown-it-py<5,>=4.0.0
|
|
13
|
+
Requires-Dist: packaging<27,>=24
|
|
14
|
+
Requires-Dist: pillow==12.2.0
|
|
15
|
+
Requires-Dist: pydantic-settings<3,>=2.7.0
|
|
16
|
+
Requires-Dist: pydantic<3,>=2.10.0
|
|
17
|
+
Requires-Dist: tenacity==9.1.4
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# Hermes VK Community
|
|
21
|
+
|
|
22
|
+
Плагин платформы [Hermes Agent](https://github.com/NousResearch/hermes-agent),
|
|
23
|
+
который подключает личного агента к сообщениям бота сообщества VK через
|
|
24
|
+
Community Long Poll API.
|
|
25
|
+
|
|
26
|
+
Проверяемый диапазон Hermes: `>=0.18.2,<0.19`.
|
|
27
|
+
|
|
28
|
+
Hermes `0.18.2` сам фиксирует `cryptography==46.0.7` и `Pillow==12.2.0`, для
|
|
29
|
+
которых опубликованы advisory с исправлениями в `48.0.1` и `12.3.0`.
|
|
30
|
+
До совместимого upstream-релиза supply-chain gate содержит только точечные
|
|
31
|
+
исключения конкретных advisory ID; расширять версии на стороне плагина нельзя,
|
|
32
|
+
поскольку это сделает dependency graph с Hermes `0.18.2` неразрешимым.
|
|
33
|
+
|
|
34
|
+
## Быстрая настройка
|
|
35
|
+
|
|
36
|
+
После установки плагина включите его и запустите мастер:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
hermes plugins enable vk-community
|
|
40
|
+
hermes gateway setup
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
В списке платформ выберите **VK Community**. Тот же мастер можно запустить
|
|
44
|
+
напрямую:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
hermes vk setup
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Мастер:
|
|
51
|
+
|
|
52
|
+
1. расскажет, какие настройки включить в сообществе и какие права выдать ключу;
|
|
53
|
+
2. примет ключ без отображения введённых символов;
|
|
54
|
+
3. примет обычные ссылки на сообщество и профили пользователей;
|
|
55
|
+
4. сам получит числовые VK ID;
|
|
56
|
+
5. с подтверждением сделает сообщество приватным и включит сообщения;
|
|
57
|
+
6. включит Community Long Poll `5.199` и событие входящего сообщения;
|
|
58
|
+
7. проверит ключ, доступ к сообществу, пользователей и итоговые настройки;
|
|
59
|
+
8. сохранит секрет и конфигурацию в активный профиль Hermes.
|
|
60
|
+
|
|
61
|
+
Если проверка не пройдёт, мастер не сохраняет локальную конфигурацию. Уже
|
|
62
|
+
подтверждённые изменения сообщества могут быть применены VK до последующей
|
|
63
|
+
ошибки проверки; повторный запуск безопасен, потому что настройки идемпотентны.
|
|
64
|
+
|
|
65
|
+
## Создание сообщества и ключа
|
|
66
|
+
|
|
67
|
+
Подойдёт в том числе закрытое сообщество, в котором состоите только вы.
|
|
68
|
+
|
|
69
|
+
1. [Создайте сообщество VK](https://vk.com/groups) или откройте его управление.
|
|
70
|
+
2. Включите **Сообщения сообщества**.
|
|
71
|
+
3. Настройки Long Poll можно оставить мастеру. При ручной настройке откройте
|
|
72
|
+
**Управление → Настройки → Работа с API → Long Poll API**, включите Long
|
|
73
|
+
Poll, выберите API `5.199` и отметьте только событие входящего сообщения
|
|
74
|
+
(`message_new`). Другие типы событий текущему адаптеру не нужны.
|
|
75
|
+
4. Там же откройте **Ключи доступа** и создайте ключ сообщества.
|
|
76
|
+
5. Выберите права:
|
|
77
|
+
- управление сообществом;
|
|
78
|
+
- сообщения сообщества;
|
|
79
|
+
- фотографии сообщества;
|
|
80
|
+
- документы сообщества.
|
|
81
|
+
|
|
82
|
+
Права на истории, стену, товары и заказы плагину не нужны. Права на фотографии
|
|
83
|
+
и документы используются реальными upload-flow: фото, обычные документы и
|
|
84
|
+
голосовые сообщения/TTS отправляются как нативные вложения VK. Для голоса
|
|
85
|
+
плагин преобразует исходное аудио в OGG/Opus через `ffmpeg`; если VK отклонит
|
|
86
|
+
voice-flow, безопасный fallback отправляет ZIP-документ без потери исходных байт.
|
|
87
|
+
|
|
88
|
+
Официальная отправная точка: [боты VK — начало работы](https://dev.vk.com/ru/api/bots/getting-started).
|
|
89
|
+
|
|
90
|
+
## Где взять ID
|
|
91
|
+
|
|
92
|
+
Вручную извлекать числовые ID не обязательно: мастер принимает ссылки.
|
|
93
|
+
|
|
94
|
+
- `https://vk.com/club240186772` → ID сообщества `240186772`;
|
|
95
|
+
- `https://vk.com/id7750207` → ID пользователя `7750207`;
|
|
96
|
+
- `https://vk.com/shkarupa.alex` → мастер запросит числовой ID через VK API;
|
|
97
|
+
- короткая ссылка сообщества с собственным именем тоже разрешается через API.
|
|
98
|
+
|
|
99
|
+
Можно указать несколько разрешённых профилей через запятую. Пустой список
|
|
100
|
+
запрещён: доступ к личному агенту закрыт по умолчанию.
|
|
101
|
+
|
|
102
|
+
## Где хранится ключ
|
|
103
|
+
|
|
104
|
+
Как и Telegram-токен в Hermes, ключ VK хранится под именем
|
|
105
|
+
`VK_COMMUNITY_TOKEN` в `.env` **активного профиля Hermes**, а не в YAML:
|
|
106
|
+
|
|
107
|
+
- профиль по умолчанию: обычно `~/.hermes/.env`;
|
|
108
|
+
- именованный профиль: его собственный каталог профиля и собственный `.env`.
|
|
109
|
+
|
|
110
|
+
Hermes устанавливает секретный scope конкретного профиля перед запуском
|
|
111
|
+
адаптера. Плагин читает ключ только через этот scope, поэтому при нескольких
|
|
112
|
+
профилях ключ одного профиля не подменит ключ другого.
|
|
113
|
+
|
|
114
|
+
Несекретные значения мастер записывает в `config.yaml` активного профиля:
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
platforms:
|
|
118
|
+
vk:
|
|
119
|
+
enabled: true
|
|
120
|
+
group_id: 240186772
|
|
121
|
+
allowed_user_ids:
|
|
122
|
+
- 7750207
|
|
123
|
+
typing_indicator: true
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Ключ, помещённый в `.env` этого репозитория, предназначен только для локальных
|
|
127
|
+
тестов разработчика. Он не переносится в профиль Hermes автоматически. При
|
|
128
|
+
обычной установке вводите ключ в мастере — тот использует штатную атомарную
|
|
129
|
+
запись секретов Hermes.
|
|
130
|
+
|
|
131
|
+
## Разработка без установленного пользователем Hermes
|
|
132
|
+
|
|
133
|
+
Глобально или в пользовательскую установку Hermes ничего ставить не требуется.
|
|
134
|
+
`uv` создаёт изолированное окружение проекта и устанавливает совместимую версию
|
|
135
|
+
Hermes как зависимость плагина:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
uv sync --all-packages
|
|
139
|
+
uv run pytest packages/hermes-vk-community/tests
|
|
140
|
+
uv run ruff check packages/hermes-vk-community
|
|
141
|
+
uv run pyright packages/hermes-vk-community
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
То есть тесты можно запускать до установки Hermes пользователем. Полностью без
|
|
145
|
+
кода Hermes проверить платформенный плагин нельзя: его контракт содержит классы
|
|
146
|
+
адаптеров, реестр платформ и профильное хранилище секретов. Изолированная `.venv`
|
|
147
|
+
решает это без изменения рабочей установки пользователя.
|
|
148
|
+
|
|
149
|
+
Для реальной end-to-end проверки всё равно нужны сеть, сообщество и тестовое
|
|
150
|
+
сообщение. Мастер уже выполняет безопасную часть live-проверки: API, права,
|
|
151
|
+
разрешение ID и получение Long Poll server.
|
|
152
|
+
|
|
153
|
+
## Ручная настройка
|
|
154
|
+
|
|
155
|
+
Если мастер использовать нельзя, добавьте `VK_COMMUNITY_TOKEN` в `.env`
|
|
156
|
+
активного профиля и внесите показанный выше блок `platforms.vk` в его
|
|
157
|
+
`config.yaml`. Не помещайте токен в YAML: валидатор плагина намеренно отклоняет
|
|
158
|
+
такую конфигурацию.
|
|
159
|
+
|
|
160
|
+
После изменения перезапустите gateway и напишите со своего разрешённого профиля
|
|
161
|
+
в сообщения сообщества:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
hermes gateway restart
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Hermes передаёт адаптеру Markdown. Live-проверенный профиль API `5.199`
|
|
168
|
+
использует Unicode codepoint offsets и компилирует
|
|
169
|
+
`bold`/`italic`/`underline`/`url` в `format_data`; заголовки становятся жирными. Цитаты
|
|
170
|
+
передаются как `▎` плюс курсив, списки — как Unicode-маркеры с отступами.
|
|
171
|
+
Markdown-таблицы всегда рендерятся в JPEG и отправляются фотографиями. Поэтому
|
|
172
|
+
смешанный ответ может стать упорядоченной серией сообщений: текст, таблица,
|
|
173
|
+
следующий текст. Отдельная Markdown-картинка аналогично становится фото между
|
|
174
|
+
текстовыми сообщениями. HTML и исходный Markdown в VK отправлять нельзя — клиент
|
|
175
|
+
показывает их буквально.
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
hermes vk probe-formatting --peer-id <PRIVATE_TEST_PEER_ID> \
|
|
179
|
+
--output vk-formatting-format-data-probe.json
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
`auto` использует проверенный rich-профиль; явный `rich` доступен для API
|
|
183
|
+
`5.199`, а `plain` оставлен как детерминированный fallback. Unknown profile/API
|
|
184
|
+
по-прежнему переключает `auto` в plain и отклоняет явный rich. Probe проверяет
|
|
185
|
+
send/edit, Unicode offsets и readback, после чего best-effort удаляет тестовые
|
|
186
|
+
сообщения. Подробности и текущий проверенный профиль записаны в
|
|
187
|
+
[`docs/vk-rich-text-compatibility.md`](docs/vk-rich-text-compatibility.md).
|
|
188
|
+
|
|
189
|
+
Статус «печатает» отправляется через `messages.setActivity`, если
|
|
190
|
+
`typing_indicator: true`; live-тест подтвердил и ответ API, и отображение в
|
|
191
|
+
клиенте VK.
|
|
192
|
+
|
|
193
|
+
Release live-матрица дополнительно проверяет DM reply на реальное входящее
|
|
194
|
+
сообщение, pinned media download, `format_data`, inline keyboard, photo upload
|
|
195
|
+
и восстановление подготовленного outbox после закрытия/повторного открытия
|
|
196
|
+
SQLite. Для запуска нужны только `VK_COMMUNITY_TOKEN`, `VK_GROUP_ID` и
|
|
197
|
+
`VK_TEST_PEER_ID`; тестовый пользователь должен предварительно прислать фото.
|
|
198
|
+
|
|
199
|
+
## Интерактивность, длинные ответы и pairing
|
|
200
|
+
|
|
201
|
+
Clarify-вопросы, подтверждения опасных команд и slash-confirm показываются как
|
|
202
|
+
одноразовые VK-клавиатуры. Payload — случайный opaque nonce, связанный в памяти
|
|
203
|
+
с разрешённым user ID, peer ID, сессией, допустимым действием и сроком жизни.
|
|
204
|
+
Повторный, просроченный или скопированный payload отклоняется до Hermes.
|
|
205
|
+
|
|
206
|
+
Длинные ответы и финализация streaming-preview поддерживают продолжения.
|
|
207
|
+
Доставленные части не отправляются повторно после timeout/частичной ошибки;
|
|
208
|
+
outbox сохраняет `random_id` и wire payload. После рестарта безопасные
|
|
209
|
+
`prepared`-строки досылаются, а неоднозначные `sending` переводятся в
|
|
210
|
+
`delivery_unknown` и доступны через `hermes vk doctor --delivery-unknown`.
|
|
211
|
+
Ошибка VK `914` уменьшает рабочий лимит вплоть до 256 символов и кеширует его.
|
|
212
|
+
|
|
213
|
+
Опциональный pairing включается в YAML:
|
|
214
|
+
|
|
215
|
+
```yaml
|
|
216
|
+
platforms:
|
|
217
|
+
vk:
|
|
218
|
+
pairing:
|
|
219
|
+
enabled: true
|
|
220
|
+
code_ttl_seconds: 600
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Создайте одноразовый код командой `hermes vk pair` и отправьте его боту только
|
|
224
|
+
текстом. В SQLite хранится SHA-256, а не сам код; вложения, forwards и payload
|
|
225
|
+
от непривязанного пользователя не загружаются.
|
|
226
|
+
|
|
227
|
+
## Диагностика
|
|
228
|
+
|
|
229
|
+
`hermes vk doctor` проверяет discovery/enabled, secret scope, конфликты политики,
|
|
230
|
+
identity сообщества, Community Long Poll, SQLite migration/schema, platform
|
|
231
|
+
lock, formatting profile и media flow. Флаги `--inflight` и
|
|
232
|
+
`--delivery-unknown` выводят только bounded идентификаторы и ошибки без текста
|
|
233
|
+
сообщений и секретов.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Hermes VK Community
|
|
2
|
+
|
|
3
|
+
Плагин платформы [Hermes Agent](https://github.com/NousResearch/hermes-agent),
|
|
4
|
+
который подключает личного агента к сообщениям бота сообщества VK через
|
|
5
|
+
Community Long Poll API.
|
|
6
|
+
|
|
7
|
+
Проверяемый диапазон Hermes: `>=0.18.2,<0.19`.
|
|
8
|
+
|
|
9
|
+
Hermes `0.18.2` сам фиксирует `cryptography==46.0.7` и `Pillow==12.2.0`, для
|
|
10
|
+
которых опубликованы advisory с исправлениями в `48.0.1` и `12.3.0`.
|
|
11
|
+
До совместимого upstream-релиза supply-chain gate содержит только точечные
|
|
12
|
+
исключения конкретных advisory ID; расширять версии на стороне плагина нельзя,
|
|
13
|
+
поскольку это сделает dependency graph с Hermes `0.18.2` неразрешимым.
|
|
14
|
+
|
|
15
|
+
## Быстрая настройка
|
|
16
|
+
|
|
17
|
+
После установки плагина включите его и запустите мастер:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
hermes plugins enable vk-community
|
|
21
|
+
hermes gateway setup
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
В списке платформ выберите **VK Community**. Тот же мастер можно запустить
|
|
25
|
+
напрямую:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
hermes vk setup
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Мастер:
|
|
32
|
+
|
|
33
|
+
1. расскажет, какие настройки включить в сообществе и какие права выдать ключу;
|
|
34
|
+
2. примет ключ без отображения введённых символов;
|
|
35
|
+
3. примет обычные ссылки на сообщество и профили пользователей;
|
|
36
|
+
4. сам получит числовые VK ID;
|
|
37
|
+
5. с подтверждением сделает сообщество приватным и включит сообщения;
|
|
38
|
+
6. включит Community Long Poll `5.199` и событие входящего сообщения;
|
|
39
|
+
7. проверит ключ, доступ к сообществу, пользователей и итоговые настройки;
|
|
40
|
+
8. сохранит секрет и конфигурацию в активный профиль Hermes.
|
|
41
|
+
|
|
42
|
+
Если проверка не пройдёт, мастер не сохраняет локальную конфигурацию. Уже
|
|
43
|
+
подтверждённые изменения сообщества могут быть применены VK до последующей
|
|
44
|
+
ошибки проверки; повторный запуск безопасен, потому что настройки идемпотентны.
|
|
45
|
+
|
|
46
|
+
## Создание сообщества и ключа
|
|
47
|
+
|
|
48
|
+
Подойдёт в том числе закрытое сообщество, в котором состоите только вы.
|
|
49
|
+
|
|
50
|
+
1. [Создайте сообщество VK](https://vk.com/groups) или откройте его управление.
|
|
51
|
+
2. Включите **Сообщения сообщества**.
|
|
52
|
+
3. Настройки Long Poll можно оставить мастеру. При ручной настройке откройте
|
|
53
|
+
**Управление → Настройки → Работа с API → Long Poll API**, включите Long
|
|
54
|
+
Poll, выберите API `5.199` и отметьте только событие входящего сообщения
|
|
55
|
+
(`message_new`). Другие типы событий текущему адаптеру не нужны.
|
|
56
|
+
4. Там же откройте **Ключи доступа** и создайте ключ сообщества.
|
|
57
|
+
5. Выберите права:
|
|
58
|
+
- управление сообществом;
|
|
59
|
+
- сообщения сообщества;
|
|
60
|
+
- фотографии сообщества;
|
|
61
|
+
- документы сообщества.
|
|
62
|
+
|
|
63
|
+
Права на истории, стену, товары и заказы плагину не нужны. Права на фотографии
|
|
64
|
+
и документы используются реальными upload-flow: фото, обычные документы и
|
|
65
|
+
голосовые сообщения/TTS отправляются как нативные вложения VK. Для голоса
|
|
66
|
+
плагин преобразует исходное аудио в OGG/Opus через `ffmpeg`; если VK отклонит
|
|
67
|
+
voice-flow, безопасный fallback отправляет ZIP-документ без потери исходных байт.
|
|
68
|
+
|
|
69
|
+
Официальная отправная точка: [боты VK — начало работы](https://dev.vk.com/ru/api/bots/getting-started).
|
|
70
|
+
|
|
71
|
+
## Где взять ID
|
|
72
|
+
|
|
73
|
+
Вручную извлекать числовые ID не обязательно: мастер принимает ссылки.
|
|
74
|
+
|
|
75
|
+
- `https://vk.com/club240186772` → ID сообщества `240186772`;
|
|
76
|
+
- `https://vk.com/id7750207` → ID пользователя `7750207`;
|
|
77
|
+
- `https://vk.com/shkarupa.alex` → мастер запросит числовой ID через VK API;
|
|
78
|
+
- короткая ссылка сообщества с собственным именем тоже разрешается через API.
|
|
79
|
+
|
|
80
|
+
Можно указать несколько разрешённых профилей через запятую. Пустой список
|
|
81
|
+
запрещён: доступ к личному агенту закрыт по умолчанию.
|
|
82
|
+
|
|
83
|
+
## Где хранится ключ
|
|
84
|
+
|
|
85
|
+
Как и Telegram-токен в Hermes, ключ VK хранится под именем
|
|
86
|
+
`VK_COMMUNITY_TOKEN` в `.env` **активного профиля Hermes**, а не в YAML:
|
|
87
|
+
|
|
88
|
+
- профиль по умолчанию: обычно `~/.hermes/.env`;
|
|
89
|
+
- именованный профиль: его собственный каталог профиля и собственный `.env`.
|
|
90
|
+
|
|
91
|
+
Hermes устанавливает секретный scope конкретного профиля перед запуском
|
|
92
|
+
адаптера. Плагин читает ключ только через этот scope, поэтому при нескольких
|
|
93
|
+
профилях ключ одного профиля не подменит ключ другого.
|
|
94
|
+
|
|
95
|
+
Несекретные значения мастер записывает в `config.yaml` активного профиля:
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
platforms:
|
|
99
|
+
vk:
|
|
100
|
+
enabled: true
|
|
101
|
+
group_id: 240186772
|
|
102
|
+
allowed_user_ids:
|
|
103
|
+
- 7750207
|
|
104
|
+
typing_indicator: true
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Ключ, помещённый в `.env` этого репозитория, предназначен только для локальных
|
|
108
|
+
тестов разработчика. Он не переносится в профиль Hermes автоматически. При
|
|
109
|
+
обычной установке вводите ключ в мастере — тот использует штатную атомарную
|
|
110
|
+
запись секретов Hermes.
|
|
111
|
+
|
|
112
|
+
## Разработка без установленного пользователем Hermes
|
|
113
|
+
|
|
114
|
+
Глобально или в пользовательскую установку Hermes ничего ставить не требуется.
|
|
115
|
+
`uv` создаёт изолированное окружение проекта и устанавливает совместимую версию
|
|
116
|
+
Hermes как зависимость плагина:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
uv sync --all-packages
|
|
120
|
+
uv run pytest packages/hermes-vk-community/tests
|
|
121
|
+
uv run ruff check packages/hermes-vk-community
|
|
122
|
+
uv run pyright packages/hermes-vk-community
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
То есть тесты можно запускать до установки Hermes пользователем. Полностью без
|
|
126
|
+
кода Hermes проверить платформенный плагин нельзя: его контракт содержит классы
|
|
127
|
+
адаптеров, реестр платформ и профильное хранилище секретов. Изолированная `.venv`
|
|
128
|
+
решает это без изменения рабочей установки пользователя.
|
|
129
|
+
|
|
130
|
+
Для реальной end-to-end проверки всё равно нужны сеть, сообщество и тестовое
|
|
131
|
+
сообщение. Мастер уже выполняет безопасную часть live-проверки: API, права,
|
|
132
|
+
разрешение ID и получение Long Poll server.
|
|
133
|
+
|
|
134
|
+
## Ручная настройка
|
|
135
|
+
|
|
136
|
+
Если мастер использовать нельзя, добавьте `VK_COMMUNITY_TOKEN` в `.env`
|
|
137
|
+
активного профиля и внесите показанный выше блок `platforms.vk` в его
|
|
138
|
+
`config.yaml`. Не помещайте токен в YAML: валидатор плагина намеренно отклоняет
|
|
139
|
+
такую конфигурацию.
|
|
140
|
+
|
|
141
|
+
После изменения перезапустите gateway и напишите со своего разрешённого профиля
|
|
142
|
+
в сообщения сообщества:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
hermes gateway restart
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Hermes передаёт адаптеру Markdown. Live-проверенный профиль API `5.199`
|
|
149
|
+
использует Unicode codepoint offsets и компилирует
|
|
150
|
+
`bold`/`italic`/`underline`/`url` в `format_data`; заголовки становятся жирными. Цитаты
|
|
151
|
+
передаются как `▎` плюс курсив, списки — как Unicode-маркеры с отступами.
|
|
152
|
+
Markdown-таблицы всегда рендерятся в JPEG и отправляются фотографиями. Поэтому
|
|
153
|
+
смешанный ответ может стать упорядоченной серией сообщений: текст, таблица,
|
|
154
|
+
следующий текст. Отдельная Markdown-картинка аналогично становится фото между
|
|
155
|
+
текстовыми сообщениями. HTML и исходный Markdown в VK отправлять нельзя — клиент
|
|
156
|
+
показывает их буквально.
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
hermes vk probe-formatting --peer-id <PRIVATE_TEST_PEER_ID> \
|
|
160
|
+
--output vk-formatting-format-data-probe.json
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`auto` использует проверенный rich-профиль; явный `rich` доступен для API
|
|
164
|
+
`5.199`, а `plain` оставлен как детерминированный fallback. Unknown profile/API
|
|
165
|
+
по-прежнему переключает `auto` в plain и отклоняет явный rich. Probe проверяет
|
|
166
|
+
send/edit, Unicode offsets и readback, после чего best-effort удаляет тестовые
|
|
167
|
+
сообщения. Подробности и текущий проверенный профиль записаны в
|
|
168
|
+
[`docs/vk-rich-text-compatibility.md`](docs/vk-rich-text-compatibility.md).
|
|
169
|
+
|
|
170
|
+
Статус «печатает» отправляется через `messages.setActivity`, если
|
|
171
|
+
`typing_indicator: true`; live-тест подтвердил и ответ API, и отображение в
|
|
172
|
+
клиенте VK.
|
|
173
|
+
|
|
174
|
+
Release live-матрица дополнительно проверяет DM reply на реальное входящее
|
|
175
|
+
сообщение, pinned media download, `format_data`, inline keyboard, photo upload
|
|
176
|
+
и восстановление подготовленного outbox после закрытия/повторного открытия
|
|
177
|
+
SQLite. Для запуска нужны только `VK_COMMUNITY_TOKEN`, `VK_GROUP_ID` и
|
|
178
|
+
`VK_TEST_PEER_ID`; тестовый пользователь должен предварительно прислать фото.
|
|
179
|
+
|
|
180
|
+
## Интерактивность, длинные ответы и pairing
|
|
181
|
+
|
|
182
|
+
Clarify-вопросы, подтверждения опасных команд и slash-confirm показываются как
|
|
183
|
+
одноразовые VK-клавиатуры. Payload — случайный opaque nonce, связанный в памяти
|
|
184
|
+
с разрешённым user ID, peer ID, сессией, допустимым действием и сроком жизни.
|
|
185
|
+
Повторный, просроченный или скопированный payload отклоняется до Hermes.
|
|
186
|
+
|
|
187
|
+
Длинные ответы и финализация streaming-preview поддерживают продолжения.
|
|
188
|
+
Доставленные части не отправляются повторно после timeout/частичной ошибки;
|
|
189
|
+
outbox сохраняет `random_id` и wire payload. После рестарта безопасные
|
|
190
|
+
`prepared`-строки досылаются, а неоднозначные `sending` переводятся в
|
|
191
|
+
`delivery_unknown` и доступны через `hermes vk doctor --delivery-unknown`.
|
|
192
|
+
Ошибка VK `914` уменьшает рабочий лимит вплоть до 256 символов и кеширует его.
|
|
193
|
+
|
|
194
|
+
Опциональный pairing включается в YAML:
|
|
195
|
+
|
|
196
|
+
```yaml
|
|
197
|
+
platforms:
|
|
198
|
+
vk:
|
|
199
|
+
pairing:
|
|
200
|
+
enabled: true
|
|
201
|
+
code_ttl_seconds: 600
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Создайте одноразовый код командой `hermes vk pair` и отправьте его боту только
|
|
205
|
+
текстом. В SQLite хранится SHA-256, а не сам код; вложения, forwards и payload
|
|
206
|
+
от непривязанного пользователя не загружаются.
|
|
207
|
+
|
|
208
|
+
## Диагностика
|
|
209
|
+
|
|
210
|
+
`hermes vk doctor` проверяет discovery/enabled, secret scope, конфликты политики,
|
|
211
|
+
identity сообщества, Community Long Poll, SQLite migration/schema, platform
|
|
212
|
+
lock, formatting profile и media flow. Флаги `--inflight` и
|
|
213
|
+
`--delivery-unknown` выводят только bounded идентификаторы и ошибки без текста
|
|
214
|
+
сообщений и секретов.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# VK rich-text compatibility
|
|
2
|
+
|
|
3
|
+
Live capability profile for the `hermes-vk-community` release gate.
|
|
4
|
+
|
|
5
|
+
## Tested profile
|
|
6
|
+
|
|
7
|
+
- Date: 2026-07-15
|
|
8
|
+
- VK API: `5.199`
|
|
9
|
+
- Transport: community token, `messages.send` and `messages.edit`
|
|
10
|
+
- Community: private group
|
|
11
|
+
- Client observation: VK Web; the UI did not expose an exact build number
|
|
12
|
+
- Machine artifact:
|
|
13
|
+
`tests/fixtures/vk/formatting/live-probe-format-data-2026-07-15.json`
|
|
14
|
+
- Certified profile: `format-data-v1`, using Unicode codepoint offsets
|
|
15
|
+
|
|
16
|
+
## Live results
|
|
17
|
+
|
|
18
|
+
| Candidate | API/readback | VK Web |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| `format_data` bold, italic, underline, URL | accepted and returned | styled correctly |
|
|
21
|
+
| nested ranges | accepted and returned | styled correctly |
|
|
22
|
+
| partially overlapping ranges | accepted and returned | styled correctly |
|
|
23
|
+
| `messages.edit` plus `format_data` | accepted and returned | styled correctly |
|
|
24
|
+
| raw HTML | accepted as text | tags displayed literally |
|
|
25
|
+
| raw Markdown | accepted as text | markers displayed literally |
|
|
26
|
+
| 4096 Cyrillic characters | exact length/hash readback | accepted |
|
|
27
|
+
| bare HTTPS URL | exact readback | clickable |
|
|
28
|
+
| `messages.setActivity(type="typing")` | response `1` | visibly displayed |
|
|
29
|
+
| Unicode-codepoint emoji-adjacent ranges | accepted and returned | intended bold/underline ranges |
|
|
30
|
+
| UTF-16 emoji-adjacent ranges | accepted and returned | same intended ranges in VK Web |
|
|
31
|
+
|
|
32
|
+
The live Unicode probe established that the renderer's Unicode-codepoint
|
|
33
|
+
payload styles the intended emoji-adjacent ranges in VK Web. The competing
|
|
34
|
+
UTF-16 payload was also normalized/displayed as intended by the tested client;
|
|
35
|
+
this does not change the wire contract emitted by the plugin. Python string
|
|
36
|
+
indices are therefore certified for API `5.199`, while both probe cases remain
|
|
37
|
+
in the regression artifact for future client/API reverification.
|
|
38
|
+
|
|
39
|
+
## Rendering profile
|
|
40
|
+
|
|
41
|
+
- Compile Markdown locally; never send raw HTML or Markdown markup.
|
|
42
|
+
- Map bold, italic and links to `format_data` version 1. Underline is supported
|
|
43
|
+
by the wire profile even though standard Markdown has no underline node.
|
|
44
|
+
- Render headings as bold text.
|
|
45
|
+
- Render quotes as `▎ ` followed by italic text.
|
|
46
|
+
- Render unordered and ordered lists with Unicode bullets/numbers and preserve
|
|
47
|
+
nesting with spaces.
|
|
48
|
+
- Render every Markdown table locally as one or more RGB JPEG images. JPEG is
|
|
49
|
+
the only table wire representation, independent of formatting mode.
|
|
50
|
+
- Lower a standalone Markdown image to a VK photo attachment. Keep an inline
|
|
51
|
+
image embedded in a text line as an alt-text fallback rather than guessing a
|
|
52
|
+
disruptive message split.
|
|
53
|
+
- Preserve mixed-content order by sending a sequence such as text → photo →
|
|
54
|
+
text. One logical Hermes reply is not required to fit one VK message.
|
|
55
|
+
- Rebase and clip formatting ranges after each 4096-character split.
|
|
56
|
+
- Persist each text chunk's exact `format_data` in the durable outbox so replay
|
|
57
|
+
does not silently lose styling.
|
|
58
|
+
|
|
59
|
+
`formatting.mode: auto` uses this rich profile. Explicit `rich` is accepted for
|
|
60
|
+
API `5.199`; `plain` remains a deterministic fallback that strips native text
|
|
61
|
+
ranges but retains JPEG tables. Unknown API/profile combinations continue to
|
|
62
|
+
fail closed to plain mode, and explicit `rich` is rejected for them.
|
|
63
|
+
|
|
64
|
+
## Reverification
|
|
65
|
+
|
|
66
|
+
Run the private-peer probe after changing the VK API version or supported
|
|
67
|
+
clients:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
hermes vk probe-formatting --peer-id <PRIVATE_TEST_PEER_ID> \
|
|
71
|
+
--output vk-formatting-format-data-probe.json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The command tests send/edit, nesting, partial overlap and competing Unicode
|
|
75
|
+
offset hypotheses, then removes its visible probe messages best-effort. Update
|
|
76
|
+
both the redacted artifact and the capability profile only after manual client
|
|
77
|
+
observation. Never commit a community token or private peer identifier.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
name: vk-community
|
|
2
|
+
label: VK Community
|
|
3
|
+
kind: platform
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
description: VK Community Long Poll gateway adapter for Hermes Agent.
|
|
6
|
+
author: Hermes VK Community contributors
|
|
7
|
+
requires_env:
|
|
8
|
+
- name: VK_COMMUNITY_TOKEN
|
|
9
|
+
description: VK community access token with messages, management, photos, and documents permissions
|
|
10
|
+
prompt: VK Community token
|
|
11
|
+
url: https://dev.vk.com/ru/api/bots/getting-started
|
|
12
|
+
password: true
|
|
13
|
+
category: credential
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.27.0"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "hermes-vk-community"
|
|
7
|
+
version = "1.0.2"
|
|
8
|
+
description = "VK Community Long Poll platform plugin for Hermes Agent"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11,<3.14"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Hermes VK Community contributors" }]
|
|
13
|
+
dependencies = [
|
|
14
|
+
"aiohttp>=3.14.1",
|
|
15
|
+
"aiosqlite==0.22.1",
|
|
16
|
+
"filetype==1.2.0",
|
|
17
|
+
"hermes-agent>=0.18.2",
|
|
18
|
+
"markdown-it-py>=4.0.0,<5",
|
|
19
|
+
"packaging>=24,<27",
|
|
20
|
+
"pillow==12.2.0",
|
|
21
|
+
"pydantic>=2.10.0,<3",
|
|
22
|
+
"pydantic-settings>=2.7.0,<3",
|
|
23
|
+
"tenacity==9.1.4",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.entry-points."hermes_agent.plugins"]
|
|
27
|
+
"vk-community" = "hermes_vk_community"
|
|
28
|
+
|
|
29
|
+
[tool.hatch.build.targets.wheel]
|
|
30
|
+
packages = ["src/hermes_vk_community"]
|
|
31
|
+
|
|
32
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
33
|
+
"plugin.yaml" = "hermes_vk_community/plugin.yaml"
|