SHA256
UI: исправить каналы и добавить MCP-док по чтению/дозаписи
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
# MCP: чтение и дозапись персонального публичного чата (type=100)
|
||||
|
||||
Документ для реализации MCP-инструмента, который:
|
||||
- читает переписку между двумя логинами (`from`, `to`);
|
||||
- добавляет новое сообщение от отправителя через серверный `AddBlock`.
|
||||
|
||||
Важно: речь про **персональные публичные** каналы (`channelTypeCode=100`), а не приватные DM.
|
||||
|
||||
## 1. Базовые предпосылки
|
||||
|
||||
1. У каждого пользователя свой блокчейн (`<login>-001`).
|
||||
2. Персональный публичный чат хранится как канал типа `100`:
|
||||
- у `A` канал с `channelName = B`;
|
||||
- у `B` зеркальный канал с `channelName = A`.
|
||||
3. Сообщения канала — `TEXT_POST` в линии `line_code = rootBlockNumber` канала.
|
||||
4. Запись блока возможна только при валидной подписи blockchain-ключом владельца цепочки.
|
||||
|
||||
## 2. Что должен уметь MCP-инструмент
|
||||
|
||||
Минимальный набор операций:
|
||||
|
||||
1. `read_personal_public_dialog(fromLogin, toLogin, limitPerSide=200)`
|
||||
2. `append_personal_public_message(fromLogin, toLogin, text)`
|
||||
|
||||
## 3. Алгоритм чтения переписки
|
||||
|
||||
### 3.1 Найти оба канала (прямой и зеркальный)
|
||||
|
||||
Для `fromLogin = A`, `toLogin = B`:
|
||||
|
||||
1. Запросить `ListSubscriptionsFeed` для `A` и найти owned-канал:
|
||||
- `ownerLogin == A`
|
||||
- `channelName == B`
|
||||
- `channelTypeCode == 100`
|
||||
2. Запросить `ListSubscriptionsFeed` для `B` и найти owned-канал:
|
||||
- `ownerLogin == B`
|
||||
- `channelName == A`
|
||||
- `channelTypeCode == 100`
|
||||
|
||||
Если какой-то из каналов не найден — вернуть частичный результат + флаг отсутствия зеркала.
|
||||
|
||||
### 3.2 Вычитать сообщения из каналов
|
||||
|
||||
Для каждого найденного канала вызвать `GetChannelMessages`:
|
||||
|
||||
```json
|
||||
{
|
||||
"op": "GetChannelMessages",
|
||||
"payload": {
|
||||
"login": "<текущий-login-сессии>",
|
||||
"channel": {
|
||||
"ownerBlockchainName": "...",
|
||||
"channelRootBlockNumber": 123,
|
||||
"channelRootBlockHash": "..."
|
||||
},
|
||||
"limit": 200,
|
||||
"sort": "asc"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 Склеить в единый диалог
|
||||
|
||||
1. Объединить массивы сообщений из `A->B` и `B->A`.
|
||||
2. Отсортировать по `createdAtMs`, при равенстве — по `messageRef.blockNumber`.
|
||||
3. Вернуть структуру:
|
||||
- `messages[]`
|
||||
- `directChannelFound` / `reverseChannelFound`
|
||||
- метаданные обоих каналов.
|
||||
|
||||
## 4. Алгоритм дозаписи сообщения
|
||||
|
||||
Цель: добавить сообщение **от имени `fromLogin`** в его канал `fromLogin -> toLogin`.
|
||||
|
||||
### 4.1 Найти канал отправителя
|
||||
|
||||
Через `ListSubscriptionsFeed(fromLogin)` найти owned-канал:
|
||||
- `channelName == toLogin`
|
||||
- `channelTypeCode == 100`
|
||||
|
||||
Если канал не найден — вернуть ошибку `channel_not_found`.
|
||||
|
||||
### 4.2 Отправить `AddBlock` с `TEXT_POST`
|
||||
|
||||
Использовать клиентский/серверный helper формирования `TEXT_POST` body:
|
||||
- `lineCode = channelRootBlockNumber`;
|
||||
- `prevLineNumber/prevLineHash` берутся из последнего сообщения линии;
|
||||
- подпись — blockchain private key пользователя `fromLogin`.
|
||||
|
||||
Если у вас в MCP нет приватного ключа пользователя, дозапись невозможна.
|
||||
|
||||
## 5. Контракт MCP (рекомендуемый)
|
||||
|
||||
## `read_personal_public_dialog`
|
||||
|
||||
Вход:
|
||||
```json
|
||||
{
|
||||
"fromLogin": "alice",
|
||||
"toLogin": "bob",
|
||||
"limitPerSide": 200
|
||||
}
|
||||
```
|
||||
|
||||
Выход:
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"directChannelFound": true,
|
||||
"reverseChannelFound": true,
|
||||
"messages": [
|
||||
{
|
||||
"authorLogin": "alice",
|
||||
"text": "Привет",
|
||||
"createdAtMs": 1760000000000,
|
||||
"channelSide": "alice->bob",
|
||||
"messageRef": { "blockNumber": 11, "blockHash": "..." }
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## `append_personal_public_message`
|
||||
|
||||
Вход:
|
||||
```json
|
||||
{
|
||||
"fromLogin": "alice",
|
||||
"toLogin": "bob",
|
||||
"text": "Тест"
|
||||
}
|
||||
```
|
||||
|
||||
Выход:
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"serverLastGlobalNumber": 321,
|
||||
"serverLastGlobalHash": "..."
|
||||
}
|
||||
```
|
||||
|
||||
## 6. Ограничения и безопасность
|
||||
|
||||
1. Персональный канал типа `100` сейчас публичный по модели чтения (не E2E DM).
|
||||
2. Нельзя дозаписать блок в чужой блокчейн без приватного ключа владельца (проверка подписи сервером).
|
||||
3. Для прод-инструмента нужно:
|
||||
- строгая авторизация MCP-вызовов;
|
||||
- аудит, кто и от чьего имени запрашивал чтение/запись;
|
||||
- лимиты/квоты на запись.
|
||||
|
||||
## 7. Мини-чеклист для реализации MCP
|
||||
|
||||
1. Реализовать helper поиска канала `findOwnedPersonalChannel(ownerLogin, peerLogin)`.
|
||||
2. Реализовать чтение двух сторон и merge/sort.
|
||||
3. Реализовать отправку `TEXT_POST` в найденный канал отправителя.
|
||||
4. Добавить понятные ошибки:
|
||||
- `user_not_found`
|
||||
- `channel_not_found`
|
||||
- `reverse_channel_not_found`
|
||||
- `signature_required`
|
||||
- `add_block_failed`
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# Персональный публичный чат: исправление формата блока и обратный канал
|
||||
|
||||
- краткое описание фичи:
|
||||
- Исправлен формат отправки `CreateChannel` из UI: для создания канала теперь используется версия body `1`, совместимая с серверным парсером.
|
||||
- Убрана ошибка `AddBlock: Некорректный формат блока (BAD_BLOCK_FORMAT)` при создании персонального публичного чата (тип `100`) на актуальном сервере.
|
||||
- В `channel-view` для персонального чата добавлена клиентская склейка диалога:
|
||||
- основной канал `A -> B` (владелец `A`, имя канала `B`, тип `100`);
|
||||
- зеркальный канал `B -> A` (владелец `B`, имя канала `A`, тип `100`);
|
||||
- сообщения обоих каналов показываются в одном диалоге, отсортированном по времени.
|
||||
- Если зеркальный канал не найден, показывается уведомление в шапке канала о том, что у собеседника пока не создан ответный чат.
|
||||
- Исправлена ошибка `Идентификатор канала не готов` при добавлении сообщения в ряде сценариев (например, «мои сторис»): отправка теперь использует фактически загруженный селектор канала, а не только параметры маршрута.
|
||||
- Улучшен резолв канала при открытии из поиска/прямой ссылки:
|
||||
- сначала попытка по `ownerBlockchainName + channelName`;
|
||||
- fallback по `ownerLogin + channelName`;
|
||||
- дополнительный fallback через `GetUser(owner)` с сопоставлением `blockchainName`.
|
||||
Это снижает число ложных `Канал не найден` при открытии сторис/каналов других пользователей.
|
||||
|
||||
- что именно проверять:
|
||||
- Создать персональный публичный чат через UI (`Каналы -> Чаты -> Новый персональный публичный чат`) и убедиться, что ошибка `BAD_BLOCK_FORMAT` больше не появляется.
|
||||
- Открыть созданный персональный чат `A -> B`, написать сообщение.
|
||||
- С аккаунта `B` создать зеркальный чат `B -> A`, отправить ответ.
|
||||
- Снова открыть чат у `A` и проверить, что в одном экране видны и исходящие, и входящие сообщения из зеркального канала.
|
||||
- Проверить, что при отсутствии зеркального канала в шапке отображается предупреждение.
|
||||
- Вкладка «Мои сторис»: открыть канал и отправить сообщение кнопкой «Добавить сообщение» — ошибка про неготовый идентификатор не должна появляться.
|
||||
- Вкладка «Найти канал»: открыть чужой сторис/канал по формату `user/channel` и убедиться, что канал открывается (если реально существует и доступен в выдаче).
|
||||
|
||||
- ожидаемый результат:
|
||||
- Персональный публичный чат создаётся без ошибки формата блока.
|
||||
- При наличии зеркального канала переписка отображается единым диалогом.
|
||||
- При отсутствии зеркального канала пользователь видит явное уведомление.
|
||||
- В «мои сторис» сообщение добавляется без ошибки `Идентификатор канала не готов`.
|
||||
- Открытие чужих каналов из поиска/ссылки работает стабильнее без ложного `Канал не найден`.
|
||||
|
||||
- статус:
|
||||
- pending
|
||||
Reference in New Issue
Block a user