Документировать API и сервис агента-кодера

This commit is contained in:
AidarKC
2026-05-24 08:04:44 +03:00
parent aa2644d812
commit 4b371e142d
53 changed files with 4317 additions and 18 deletions
+11 -1
View File
@@ -123,7 +123,17 @@
---
## 8. Короткое резюме
## 8. Источник истины по списку операций
Фактический список публичных WebSocket-операций берётся из:
- `shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonHandlerRegistry.java`.
Если операция зарегистрирована в `HANDLERS` и `REQUEST_TYPES`, она считается доступной через JSON/WebSocket API. Общий актуальный индекс таких операций поддерживается в `Dev_Docs/API/09_Operations_Index.md`.
---
## 9. Короткое резюме
- Запросы всегда идут как `op + requestId + payload`.
- Ответы всегда идут как `op + requestId + status + ok + payload`.
+45 -3
View File
@@ -2,10 +2,11 @@
Этот файл описывает временный раздел API, связанный с заведением пользователя на сервере и проверкой, существует ли пользователь.
Сейчас здесь два метода:
Сейчас здесь три метода:
- `AddUser` — временная серверная регистрация пользователя;
- `GetUser` — временная серверная проверка существования пользователя и чтение его базовых данных.
- `GetUser` — временная серверная проверка существования пользователя и чтение его базовых данных;
- `SearchUsers` — dev/test поиск логинов по префиксу.
Их логика пока вспомогательная и dev-oriented: сервер сам хранит эти данные локально и сам отвечает на existence-check. В будущем оба сценария должны быть заменены на нормальную работу напрямую через Solana, но пока этот контракт нужен клиентам для разработки и интеграции.
@@ -166,8 +167,49 @@
---
## 3. Короткое резюме
## 3. Операция `SearchUsers`
### Назначение
Поиск пользователей по префиксу логина. Операция зарегистрирована в серверном API и используется как вспомогательная dev/test операция.
### Запрос
```json
{
"op": "SearchUsers",
"requestId": "search-001",
"payload": {
"prefix": "an"
}
}
```
### Успешный ответ
```json
{
"op": "SearchUsers",
"requestId": "search-001",
"status": 200,
"ok": true,
"payload": {
"logins": ["anya", "andrey"]
}
}
```
### Специфические коды ошибок `SearchUsers`
- `400 / BAD_FIELDS` — некорректный или пустой `prefix`.
- `501 / DB_ERROR` — ошибка БД при поиске.
- `500 / INTERNAL_ERROR` — непредвиденная внутренняя ошибка сервера.
---
## 4. Короткое резюме
- `AddUser` — временная регистрация пользователя на сервере.
- `GetUser` — временная проверка существования пользователя на сервере.
- `SearchUsers` — временный поиск пользователей по префиксу.
- И регистрация, и existence-check позже должны быть переведены на Solana.
+182 -6
View File
@@ -1,11 +1,15 @@
# API для разработчиков: Технические запросы
Этот файл описывает технические запросы, которые не требуют авторизации и нужны для служебной работы клиента с сервером.
Этот файл описывает технические WebSocket-запросы, которые нужны для служебной работы клиента с сервером. Часть операций доступна без авторизации, часть требует успешной авторизованной сессии.
Сейчас здесь два метода:
Сейчас здесь шесть методов:
- `Ping` — keep-alive запрос для поддержания живого WebSocket-соединения;
- `GetServerInfo` — запрос базовой публичной информации о сервере для выбора узла в децентрализованной сети.
- `GetServerInfo` — запрос базовой публичной информации о сервере для выбора узла в децентрализованной сети;
- `GetCallIceConfig` — выдача STUN/TURN конфигурации для звонков;
- `ClientErrorLog` — отправка клиентской ошибки в серверный лог;
- `ClientDebugLog` — отправка клиентского debug-события в серверный буфер;
- `CallDeliveryReport` — диагностический отчёт клиента о доставке/установке звонка.
Логика раздела такая:
@@ -130,14 +134,186 @@
---
## 3. Короткое резюме
## 3. `GetCallIceConfig`
Доступно только после успешной авторизации.
### Запрос
```json
{
"op": "GetCallIceConfig",
"requestId": "ice-001",
"payload": {
}
}
```
### Успешный ответ
```json
{
"op": "GetCallIceConfig",
"requestId": "ice-001",
"status": 200,
"ok": true,
"payload": {
"stunUrls": ["stun:stun.example.org:3478"],
"turnUrls": ["turn:turn.example.org:3478?transport=udp"],
"turnUsername": "user",
"turnPassword": "password",
"turnServers": [
{
"id": "primary",
"urls": ["turn:turn.example.org:3478?transport=udp"],
"username": "user",
"password": "password"
}
],
"turnEnabled": true,
"generatedAtMs": 1774700000123,
"expiresAtMs": 1774700300123,
"ttlSec": 300
}
}
```
### Специфические коды ошибок `GetCallIceConfig`
- `422 / NOT_AUTHENTICATED` — требуется авторизация.
---
## 4. `ClientErrorLog`
### Запрос
```json
{
"op": "ClientErrorLog",
"requestId": "err-001",
"payload": {
"kind": "global_error",
"message": "TypeError: failed",
"stack": "...",
"sourceUrl": "https://shineup.me/app.js",
"lineNumber": 10,
"columnNumber": 20,
"route": "#/channel-view/own-0",
"href": "https://shineup.me/#/channel-view/own-0",
"userAgent": "...",
"clientTs": 1774700000123,
"requestOp": "GetChannelMessages",
"requestIdRef": "GetChannelMessages-123",
"contextJson": "{\"screen\":\"channels\"}"
}
}
```
### Успешный ответ
```json
{
"op": "ClientErrorLog",
"requestId": "err-001",
"status": 200,
"ok": true,
"payload": {
"serverTs": 1774700000456,
"accepted": true
}
}
```
### Специфические коды ошибок `ClientErrorLog`
- `400 / BAD_FIELDS` — обязательные поля ошибки не заполнены.
---
## 5. `ClientDebugLog`
### Запрос
```json
{
"op": "ClientDebugLog",
"requestId": "dbg-001",
"payload": {
"runId": "ui-run-1",
"level": "info",
"message": "opened channels tab",
"details": "{\"route\":\"#/channels\"}"
}
}
```
### Успешный ответ
```json
{
"op": "ClientDebugLog",
"requestId": "dbg-001",
"status": 200,
"ok": true,
"payload": {
"accepted": true,
"serverTs": 1774700000456
}
}
```
### Специфические коды ошибок `ClientDebugLog`
- `400 / BAD_FIELDS` — поле `message` не заполнено.
---
## 6. `CallDeliveryReport`
### Запрос
```json
{
"op": "CallDeliveryReport",
"requestId": "call-report-001",
"payload": {
"type": "outgoing_failed",
"value": "{\"reason\":\"ice_failed\",\"callId\":\"call-1\"}"
}
}
```
### Успешный ответ
```json
{
"op": "CallDeliveryReport",
"requestId": "call-report-001",
"status": 200,
"ok": true,
"payload": {
"serverTs": 1774700000456,
"accepted": true
}
}
```
### Специфические коды ошибок `CallDeliveryReport`
- `400 / BAD_FIELDS` — поле `type` не заполнено.
---
## 7. Короткое резюме
- `Ping` нужен для keep-alive и проверки, что WebSocket-соединение живо.
- `GetServerInfo` нужен для выбора сервера в сети и показа публичной информации об узле.
- Оба запроса доступны без авторизации.
- `GetCallIceConfig` нужен для WebRTC-звонков и требует авторизации.
- `ClientErrorLog`, `ClientDebugLog`, `CallDeliveryReport` используются для диагностики клиента и звонков.
## 4. Прямое техническое сообщение в конкретную сессию
## 8. Прямое техническое сообщение в конкретную сессию
На текущий момент в публичном JSON API этого документа **нет отдельного RPC** для отправки произвольного технического сообщения в конкретную сессию пользователя (по `sessionId`).
+127 -1
View File
@@ -1,7 +1,7 @@
# 06. Channels Read API
## Человеко-читаемое объяснение
Эти 3 функции — это **чтение данных каналов** для UI:
Эти функции — это **чтение данных каналов** для UI:
1. `ListSubscriptionsFeed` — отдает данные для экрана списка каналов:
- ваши каналы (личный + созданные вами),
@@ -14,6 +14,12 @@
3. `GetMessageThread` — отдает дерево обсуждения вокруг конкретного сообщения:
предки, фокус-сообщение, потомки.
4. `GetChannelsCounters` — отдает счетчики разделов каналов для пользователя.
5. `ListGroupChats200` — отдает список групповых чатов типа `200`.
6. `GetGroupDialog` — отдает сообщения конкретного группового чата типа `200`.
> На первом этапе мы **не используем курсоры** (`nextCursor`) и загружаем полные списки.
---
@@ -198,6 +204,126 @@
---
## 4) GetChannelsCounters
### Request
```json
{
"op": "GetChannelsCounters",
"requestId": "req-4",
"payload": {
"login": "Alice"
}
}
```
### Response (success)
```json
{
"op": "GetChannelsCounters",
"requestId": "req-4",
"status": 200,
"ok": true,
"payload": {
"login": "Alice",
"feedCount": 12,
"dialogs100Count": 3,
"groupChats200Count": 4,
"myChannelsCount": 2
}
}
```
---
## 5) ListGroupChats200
### Request
```json
{
"op": "ListGroupChats200",
"requestId": "req-5",
"payload": {
"login": "Alice"
}
}
```
### Response (success)
```json
{
"op": "ListGroupChats200",
"requestId": "req-5",
"status": 200,
"ok": true,
"payload": {
"login": "Alice",
"chats": [
{
"ownerLogin": "Alice",
"ownerBlockchainName": "alice-001",
"channelRootBlockNumber": 123,
"channelRootBlockHash": "...",
"channelName": "team",
"chatTitle": "Team chat",
"membersCount": 3,
"updatedAtMs": 1760000000000
}
]
}
}
```
---
## 6) GetGroupDialog
### Request
```json
{
"op": "GetGroupDialog",
"requestId": "req-6",
"payload": {
"login": "Alice",
"group": {
"ownerBlockchainName": "alice-001",
"channelRootBlockNumber": 123
}
}
}
```
### Response (success)
```json
{
"op": "GetGroupDialog",
"requestId": "req-6",
"status": 200,
"ok": true,
"payload": {
"group": {
"ownerLogin": "Alice",
"ownerBlockchainName": "alice-001",
"channelRootBlockNumber": 123,
"channelName": "team",
"chatTitle": "Team chat"
},
"messages": [
{
"authorLogin": "Bob",
"authorBlockchainName": "bob-001",
"blockNumber": 140,
"blockHash": "...",
"createdAtMs": 1760000000000,
"text": "Привет"
}
]
}
}
```
---
## Reason codes
- `bad_fields`
- `user_not_found`
+58
View File
@@ -0,0 +1,58 @@
# API для разработчиков: индекс операций
Этот файл фиксирует полный список публичных JSON/WebSocket операций, зарегистрированных в коде сервера.
Источник истины на момент актуализации:
- `shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonHandlerRegistry.java`.
Если операция есть в `HANDLERS` и `REQUEST_TYPES`, клиент может отправлять её как `op` в общем JSON-конверте из `00_Common_API_Format.md`.
## Актуальные операции
| Операция | Раздел документации | Кратко |
| --- | --- | --- |
| `AddUser` | `01_User_Registration_API.md` | временная регистрация пользователя |
| `GetUser` | `01_User_Registration_API.md` | чтение/проверка пользователя |
| `SearchUsers` | `01_User_Registration_API.md` | поиск логинов по префиксу |
| `AuthChallenge` | `02_Authentication_API.md` | challenge для создания новой сессии |
| `CreateAuthSession` | `02_Authentication_API.md` | создание новой авторизованной сессии |
| `SessionChallenge` | `02_Authentication_API.md` | challenge для входа в существующую сессию |
| `SessionLogin` | `02_Authentication_API.md` | вход в существующую сессию |
| `ListSessions` | `03_Session_Management_API.md` | список активных сессий |
| `CloseActiveSession` | `03_Session_Management_API.md` | закрытие активной сессии |
| `AddBlock` | `04_Add_Block_to_Blockchain_API.md` | добавление блока в блокчейн |
| `Ping` | `05_Technical_Requests_API.md` | keep-alive |
| `GetServerInfo` | `05_Technical_Requests_API.md` | публичная информация о сервере |
| `GetCallIceConfig` | `05_Technical_Requests_API.md` | STUN/TURN конфигурация звонков |
| `ClientErrorLog` | `05_Technical_Requests_API.md` | логирование клиентской ошибки |
| `ClientDebugLog` | `05_Technical_Requests_API.md` | клиентский debug-лог |
| `CallDeliveryReport` | `05_Technical_Requests_API.md` | диагностика доставки/установки звонков |
| `ListSubscriptionsFeed` | `06_Channels_Read_API.md` | лента каналов/подписок |
| `GetChannelMessages` | `06_Channels_Read_API.md` | сообщения канала |
| `GetMessageThread` | `06_Channels_Read_API.md` | тред сообщения |
| `GetChannelsCounters` | `06_Channels_Read_API.md` | счетчики разделов каналов |
| `ListGroupChats200` | `06_Channels_Read_API.md` | список групповых чатов типа `200` |
| `GetGroupDialog` | `06_Channels_Read_API.md` | сообщения группового чата типа `200` |
| `UpsertUserParam` | `10_User_Params_API.md` | запись параметра пользователя |
| `GetUserParam` | `10_User_Params_API.md` | чтение одного параметра пользователя |
| `ListUserParams` | `10_User_Params_API.md` | список параметров пользователя |
| `GetFriendsLists` | `11_Connections_API.md` | входящие/исходящие друзья |
| `ListContacts` | `11_Connections_API.md` | контакты текущего пользователя |
| `GetUserConnectionsGraph` | `11_Connections_API.md` | граф связей пользователя |
| `AddCloseFriend` | `11_Connections_API.md` | добавить близкого друга |
| `UpsertPushToken` | `12_Direct_Messages_Push_Calls_API.md` | регистрация WebPush-токена |
| `SendTestWebPush` | `12_Direct_Messages_Push_Calls_API.md` | тестовая push-доставка |
| `SendDirectMessage` | `12_Direct_Messages_Push_Calls_API.md` | отправка подписанного DM-пакета |
| `SendMessagePair` | `12_Direct_Messages_Push_Calls_API.md` | отправка пары входящий/исходящий DM |
| `ReceiveOutcomingMessage` | `12_Direct_Messages_Push_Calls_API.md` | алиас `SendMessagePair` |
| `ReceiveIncomingMessage` | `12_Direct_Messages_Push_Calls_API.md` | прием входящего DM-блока |
| `AckSessionDelivery` | `12_Direct_Messages_Push_Calls_API.md` | подтверждение доставки в сессию |
| `CallInviteBroadcast` | `12_Direct_Messages_Push_Calls_API.md` | broadcast приглашения к звонку |
| `CallSignalToSession` | `12_Direct_Messages_Push_Calls_API.md` | сигнал звонка в конкретную сессию |
## Важные замечания
- `ReceiveOutcomingMessage` сейчас зарегистрирован как алиас того же handler/request-класса, что и `SendMessagePair`.
- Классы `Net_MarkChannelMessagesSeen_*` существуют в коде, но операция `MarkChannelMessagesSeen` не зарегистрирована в `JsonHandlerRegistry`, поэтому в публичный список API не входит.
- HTTP debug endpoints из `src/main/java/server/debug/` не входят в этот индекс WebSocket `op`; они описаны отдельно в `13_HTTP_Debug_API.md`.
+129
View File
@@ -0,0 +1,129 @@
# API для разработчиков: параметры пользователя
Документ описывает операции для записи и чтения пользовательских параметров.
Текущие операции:
- `UpsertUserParam`
- `GetUserParam`
- `ListUserParams`
## 1. `UpsertUserParam`
### Запрос
```json
{
"op": "UpsertUserParam",
"requestId": "param-upsert-001",
"payload": {
"login": "alice",
"param": "display_name",
"time_ms": 1774700000123,
"value": "Alice",
"device_key": "BASE64_DEVICE_PUBLIC_KEY",
"signature": "BASE64_SIGNATURE"
}
}
```
### Успешный ответ
```json
{
"op": "UpsertUserParam",
"requestId": "param-upsert-001",
"status": 200,
"ok": true,
"payload": {
}
}
```
### Типовые ошибки
- `400 / BAD_FIELDS` — некорректные обязательные поля.
- `422 / BAD_SIGNATURE` — подпись не прошла проверку.
- `501 / DB_ERROR` — ошибка БД.
---
## 2. `GetUserParam`
### Запрос
```json
{
"op": "GetUserParam",
"requestId": "param-get-001",
"payload": {
"login": "alice",
"param": "display_name"
}
}
```
### Успешный ответ
```json
{
"op": "GetUserParam",
"requestId": "param-get-001",
"status": 200,
"ok": true,
"payload": {
"login": "alice",
"param": "display_name",
"time_ms": 1774700000123,
"value": "Alice",
"device_key": "BASE64_DEVICE_PUBLIC_KEY",
"signature": "BASE64_SIGNATURE"
}
}
```
Если параметр не найден, сервер возвращает `404` с пустым `payload`; отдельный прикладной код ошибки текущий handler не задаёт.
---
## 3. `ListUserParams`
### Запрос
```json
{
"op": "ListUserParams",
"requestId": "param-list-001",
"payload": {
"login": "alice"
}
}
```
### Успешный ответ
```json
{
"op": "ListUserParams",
"requestId": "param-list-001",
"status": 200,
"ok": true,
"payload": {
"login": "alice",
"params": [
{
"login": "alice",
"param": "display_name",
"time_ms": 1774700000123,
"value": "Alice",
"device_key": "BASE64_DEVICE_PUBLIC_KEY",
"signature": "BASE64_SIGNATURE"
}
]
}
}
```
## Примечание
Имена JSON-полей `time_ms` и `device_key` сейчас соответствуют Java-модели ответа/запроса и должны передаваться именно в таком виде.
+174
View File
@@ -0,0 +1,174 @@
# API для разработчиков: связи пользователей
Документ описывает операции чтения и записи пользовательских связей.
Текущие операции:
- `GetFriendsLists`
- `ListContacts`
- `GetUserConnectionsGraph`
- `AddCloseFriend`
## 1. `GetFriendsLists`
### Запрос
```json
{
"op": "GetFriendsLists",
"requestId": "friends-001",
"payload": {
"login": "alice"
}
}
```
### Успешный ответ
```json
{
"op": "GetFriendsLists",
"requestId": "friends-001",
"status": 200,
"ok": true,
"payload": {
"login": "Alice",
"out_friends": ["Bob"],
"in_friends": ["Kate"]
}
}
```
---
## 2. `ListContacts`
`ListContacts` использует текущую авторизованную сессию. В payload нет дополнительных полей.
### Запрос
```json
{
"op": "ListContacts",
"requestId": "contacts-001",
"payload": {
}
}
```
### Успешный ответ
```json
{
"op": "ListContacts",
"requestId": "contacts-001",
"status": 200,
"ok": true,
"payload": {
"login": "Alice",
"contacts": ["Bob", "Kate"]
}
}
```
---
## 3. `GetUserConnectionsGraph`
### Запрос
```json
{
"op": "GetUserConnectionsGraph",
"requestId": "graph-001",
"payload": {
"login": "alice"
}
}
```
### Успешный ответ
```json
{
"op": "GetUserConnectionsGraph",
"requestId": "graph-001",
"status": 200,
"ok": true,
"payload": {
"login": "Alice",
"outFriends": ["Bob"],
"inFriends": ["Kate"],
"outContacts": [],
"inContacts": [],
"outFollows": [],
"inFollows": [],
"outSpouses": [],
"inSpouses": [],
"outParents": [],
"inParents": [],
"outChildren": [],
"inChildren": [],
"outSiblings": [],
"inSiblings": [],
"outKnownPersons": [],
"inKnownPersons": [],
"outShineConfirmed": [],
"inShineConfirmed": [],
"outShineSeen": [],
"inShineSeen": [],
"parents": [],
"children": [],
"siblings": [],
"spouses": [],
"allUsers": [
{
"login": "Bob",
"official": false,
"shine": true,
"officialLabel": "",
"shineLabel": "shine",
"avatar": { "ar": "..." }
}
]
}
}
```
### Примечание
Поля `known_person`, `shine_confirmed`, `shine_seen` в UI считаются недопроверенной зоной проекта; при изменениях этой логики нужна ручная end-to-end проверка.
---
## 4. `AddCloseFriend`
`AddCloseFriend` использует текущую авторизованную сессию как источник `login`.
### Запрос
```json
{
"op": "AddCloseFriend",
"requestId": "close-friend-001",
"payload": {
"toLogin": "bob"
}
}
```
### Успешный ответ
```json
{
"op": "AddCloseFriend",
"requestId": "close-friend-001",
"status": 200,
"ok": true,
"payload": {
"login": "Alice",
"toLogin": "Bob",
"relation": "close_friend"
}
}
```
@@ -0,0 +1,306 @@
# API для разработчиков: DM, push и сигналы звонков
Документ описывает WebSocket-операции для подписанных личных сообщений, WebPush и realtime-сигналов звонков.
Логика личных сообщений дополнительно описана в `Dev_Docs/Personal_Messages/README.md`; этот файл фиксирует именно публичные `op`, поля запросов и поля ответов.
## 1. `UpsertPushToken`
Требует авторизации.
### Запрос
```json
{
"op": "UpsertPushToken",
"requestId": "push-upsert-001",
"payload": {
"sessionId": "SESSION_ID",
"endpoint": "https://push.example/...",
"p256dhKey": "BASE64",
"authKey": "BASE64",
"platform": "web",
"userAgent": "Mozilla/5.0 ..."
}
}
```
### Успешный ответ
```json
{
"op": "UpsertPushToken",
"requestId": "push-upsert-001",
"status": 200,
"ok": true,
"payload": {
"tokenId": "token-1",
"updatedAtMs": 1774700000123
}
}
```
---
## 2. `SendTestWebPush`
Требует авторизации. Если `login` передан, он должен совпадать с логином текущей сессии.
### Запрос
```json
{
"op": "SendTestWebPush",
"requestId": "push-test-001",
"payload": {
"login": "alice",
"sessionId": "SESSION_ID",
"title": "Test",
"text": "Push body"
}
}
```
### Успешный ответ
```json
{
"op": "SendTestWebPush",
"requestId": "push-test-001",
"status": 200,
"ok": true,
"payload": {
"targetLogin": "alice",
"attemptedSessions": 1,
"sessionsWithPushConfig": 1,
"delivered": 1,
"failed": 0,
"sentAtMs": 1774700000123
}
}
```
---
## 3. `SendDirectMessage`
Отправляет один подписанный DM-пакет.
### Запрос
```json
{
"op": "SendDirectMessage",
"requestId": "dm-001",
"payload": {
"blobB64": "BASE64_SIGNED_DM_PACKET"
}
}
```
### Успешный ответ
```json
{
"op": "SendDirectMessage",
"requestId": "dm-001",
"status": 200,
"ok": true,
"payload": {
"messageId": "dm-1",
"deliveredWsSessions": 1,
"deliveredWebPushSessions": 0,
"sessionNotFound": false
}
}
```
---
## 4. `SendMessagePair` и `ReceiveOutcomingMessage`
`ReceiveOutcomingMessage` сейчас является алиасом `SendMessagePair` и использует тот же request/handler.
### Запрос
```json
{
"op": "SendMessagePair",
"requestId": "dm-pair-001",
"payload": {
"incomingBlobB64": "BASE64_INCOMING_SIGNED_BLOCK",
"outgoingBlobB64": "BASE64_OUTGOING_SIGNED_BLOCK"
}
}
```
### Успешный ответ
```json
{
"op": "SendMessagePair",
"requestId": "dm-pair-001",
"status": 200,
"ok": true,
"payload": {
"baseKey": "base-key",
"incomingKey": "incoming-key",
"outgoingKey": "outgoing-key",
"deliveredWsSessions": 1,
"deliveredWebPushSessions": 0
}
}
```
---
## 5. `ReceiveIncomingMessage`
Принимает входящий подписанный DM-блок.
### Запрос
```json
{
"op": "ReceiveIncomingMessage",
"requestId": "dm-in-001",
"payload": {
"incomingBlobB64": "BASE64_INCOMING_SIGNED_BLOCK"
}
}
```
### Успешный ответ
```json
{
"op": "ReceiveIncomingMessage",
"requestId": "dm-in-001",
"status": 200,
"ok": true,
"payload": {
"messageKey": "incoming-key",
"baseKey": "base-key",
"deliveredWsSessions": 1,
"deliveredWebPushSessions": 0
}
}
```
---
## 6. `AckSessionDelivery`
Требует авторизации. Подтверждает доставку сообщения в текущую сессию.
### Запрос
```json
{
"op": "AckSessionDelivery",
"requestId": "ack-001",
"payload": {
"messageKey": "incoming-key"
}
}
```
### Успешный ответ
```json
{
"op": "AckSessionDelivery",
"requestId": "ack-001",
"status": 200,
"ok": true,
"payload": {
"messageKey": "incoming-key"
}
}
```
---
## 7. `CallInviteBroadcast`
Требует авторизации. Отправляет приглашение к звонку на активные сессии пользователя `toLogin`.
### Запрос
```json
{
"op": "CallInviteBroadcast",
"requestId": "call-invite-001",
"payload": {
"toLogin": "bob",
"callId": "call-1",
"type": 100
}
}
```
### Успешный ответ
```json
{
"op": "CallInviteBroadcast",
"requestId": "call-invite-001",
"status": 200,
"ok": true,
"payload": {
"callId": "call-1",
"deliveredWsSessions": 1,
"deliveredFcmSessions": 0,
"deliveredWebPushSessions": 0
}
}
```
---
## 8. `CallSignalToSession`
Требует авторизации. Отправляет сигнал звонка в конкретную сессию получателя.
### Запрос
```json
{
"op": "CallSignalToSession",
"requestId": "call-signal-001",
"payload": {
"toLogin": "bob",
"targetSessionId": "SESSION_ID",
"callId": "call-1",
"type": 101,
"data": "{\"sdp\":\"...\"}"
}
}
```
### Успешный ответ
```json
{
"op": "CallSignalToSession",
"requestId": "call-signal-001",
"status": 200,
"ok": true,
"payload": {
"delivered": true
}
}
```
Если целевая сессия не найдена или доставка не удалась, сервер может вернуть `404`.
## Типовые ошибки
- `422 / NOT_AUTHENTICATED` — требуется авторизация.
- `400 / BAD_FIELDS` — не заполнены обязательные поля.
- `404 / USER_NOT_FOUND` — пользователь не найден.
- `404 / SESSION_NOT_FOUND` — сессия не найдена.
- `422 / BAD_SIGNATURE` — подпись DM не прошла проверку.
- `422 / BAD_DEVICE_KEY` — некорректный device key отправителя.
- `422 / BAD_TIME_WINDOW` — время подписанного сообщения вне допустимого окна.
- `422 / REPLAY` — повторное сообщение заблокировано.
+190
View File
@@ -0,0 +1,190 @@
# API для разработчиков: HTTP debug endpoints
Этот файл описывает отдельный HTTP debug API сервера. Он не использует WebSocket-конверт `op/requestId/payload` и включается только настройкой:
- `debug.tempApi.enabled=true`
Источник истины:
- `src/main/java/server/debug/DebugApiConfigurator.java`
- `src/main/java/server/debug/*Servlet.java`
Если `.debug-token` отсутствует или пуст, endpoints возвращают `503 / DEBUG_DISABLED`.
## Авторизация
Для большинства debug endpoints используется Bearer token из `.debug-token`:
```http
Authorization: Bearer <token>
```
Для `POST /debug/ws/ui-reload-all` поддерживается заголовок:
```http
X-Debug-Token: <token>
```
При неверном токене сервер возвращает `401 / UNAUTHORIZED`.
## Формат успешного HTTP-ответа
```json
{
"ok": true,
"payload": {
}
}
```
## Формат HTTP-ошибки
```json
{
"ok": false,
"code": "BAD_JSON",
"message": "Тело запроса должно быть JSON"
}
```
## 1. `GET /debug/ws/clients`
Возвращает список активных WebSocket-клиентов.
### Успешный ответ
```json
{
"ok": true,
"payload": {
"count": 1,
"clients": [
{
"sessionId": "SESSION_ID",
"login": "alice",
"authStatus": 2,
"wsOpen": true,
"remoteAddress": "127.0.0.1",
"ip": "127.0.0.1",
"userAgent": "Mozilla/5.0 ...",
"clientInfoFromClient": "...",
"clientInfoFromRequest": "...",
"userLanguage": "ru",
"sessionCreatedAtMs": 1774700000123
}
]
}
}
```
## 2. `POST /debug/ws/connect`
Запускает debug-сценарий соединения двух активных WS-сессий и отправляет им события:
- `DebugConnectPrepareResponder`
- `DebugConnectStartInitiator`
### Запрос
```json
{
"initiatorSessionId": "SESSION_ID_1",
"responderSessionId": "SESSION_ID_2",
"clearDebugLog": true
}
```
### Успешный ответ
```json
{
"ok": true,
"payload": {
"runId": "dbg-...",
"callId": "debug-call-...",
"accepted": true,
"initiatorSessionId": "SESSION_ID_1",
"responderSessionId": "SESSION_ID_2",
"initiatorLogin": "alice",
"responderLogin": "bob",
"mode": "cross-login"
}
}
```
### Ошибки
- `400 / BAD_JSON` — тело запроса не JSON.
- `400 / BAD_FIELDS` — не заполнены sessionId или переданы одинаковые sessionId.
- `404 / INITIATOR_NOT_FOUND` — сессия инициатора не найдена или неактивна.
- `404 / RESPONDER_NOT_FOUND` — сессия получателя не найдена или неактивна.
## 3. `GET /debug/ws/logs`
Возвращает tail debug-логов из `DebugRunLogBuffer`.
### Query-параметры
- `limit` — количество записей.
- `runId` — фильтр по runId.
### Успешный ответ
```json
{
"ok": true,
"payload": {
"count": 1,
"limit": 100,
"runIdFilter": "ui-run-1",
"logs": [
{
"ts": 1774700000123,
"level": "info",
"runId": "ui-run-1",
"source": "debug-connect",
"sessionId": "SESSION_ID",
"login": "alice",
"message": "opened channels tab",
"details": "{}"
}
]
}
}
```
## 4. `POST /debug/ws/ui-reload-all`
Рассылает активным UI-сессиям debug-событие на reload.
### Запрос
```json
{
"reason": "manual_debug_api",
"reloadAfterMs": 700
}
```
Если `reason` не передан или пустой, сервер использует `manual_debug_api`. `reloadAfterMs` ограничивается диапазоном `100..15000`.
### Успешный ответ
```json
{
"ok": true,
"payload": {
"accepted": true,
"reason": "manual_debug_api",
"reloadAfterMs": 700,
"issuedAtMs": 1774700000123,
"totalConnections": 2,
"sentCount": 2,
"skippedCount": 0
}
}
```
### Ошибки
- `400 / BAD_JSON` — тело запроса не JSON.
@@ -0,0 +1,18 @@
# SHiNE-agent-bot-coder: очередь, voice, codex, systemd
- краткое описание фичи:
Добавлен новый сервис `SHiNE-agent-bot-coder` (Java), который обрабатывает сообщения от `@AidarKC`, ведёт JSONL-историю, использует файловую очередь, распознаёт voice через OpenAI, вызывает Codex CLI и поддерживает запуск как `systemd`-сервис.
- что именно проверять:
1. Бот принимает текст от `@AidarKC`, ставит задачу в очередь и отправляет ответ от Codex.
2. Бот принимает voice, отправляет текст распознавания и затем ответ от Codex.
3. Одновременные сообщения обрабатываются строго по одному (без параллельных запусков Codex).
4. После рестарта сервиса незавершённая активная задача повторно уходит в обработку.
5. Команда `/new` архивирует текущую историю и создаёт новую.
6. `systemd`-сервис стартует и автоматически перезапускается.
- ожидаемый результат:
Все пункты выше отрабатывают без потери сообщений, с корректным обновлением `data/queue.jsonl`, `data/state.json` и `data/history/*.jsonl`.
- статус:
`pending`
@@ -0,0 +1,22 @@
# Агент-бот coder: устранение дублей и зависаний
- краткое описание фичи:
- добавлен lock-файл `data/app.lock`, чтобы гарантировать единственный инстанс бота;
- доработано завершение worker/codex при stop/restart, чтобы не было ложных retry после штатной остановки;
- синхронизирован systemd-профиль под `--user` для `ai`;
- улучшена отправка промежуточных статусов по событиям `codex --json`.
- что проверять:
- при запущенном сервисе повторный запуск jar вручную завершается сразу с сообщением про занятый lock;
- команда `/status` отвечает один раз (без дублей);
- тестовая текстовая задача от `@AidarKC` обрабатывается и возвращает ответ;
- при `/stop` активная задача завершается без последующего спама retry-ошибками;
- в логах нет `409 Conflict` из-за второго poller после чистого перезапуска.
- ожидаемый результат:
- одновременно работает только один процесс бота;
- бот не дублирует ответы;
- очередь не застревает на interrupted после штатного stop/restart.
- статус:
- pending
@@ -0,0 +1,21 @@
# Python-обвязка Telegram → Codex (упрощённый сервис)
- краткое описание фичи:
- добавлен новый упрощённый сервис `SHiNE-agent-bot-coder/py_bot_service.py`;
- сервис работает через long-polling Telegram, принимает только текст, ведёт историю в `JSONL`;
- добавлены команды `/status`, `/queue`, `/stop`, `/cancel`, `/new`, `/help`;
- systemd unit переключён на запуск Python-сервиса.
- что проверять:
- `systemctl --user status shine-agent-bot-coder` показывает `active (running)`;
- бот отвечает на `/status` одним сообщением без дублей;
- тестовый текстовый запрос получает финальный ответ от Codex;
- `/stop` корректно останавливает текущую задачу;
- `/new` переносит текущую историю в `data/history/archive`.
- ожидаемый результат:
- стабильная обработка текстовых задач без зависаний и двойной обработки;
- только один инстанс сервиса (через lock `data/py_app.lock`).
- статус:
- pending
@@ -0,0 +1,36 @@
# Локальный деплой SHiNE-agent-bot-coder (systemd, пользователь ai)
## Где находится сервис
- Папка сервиса: `SHiNE-agent-bot-coder/`
- Systemd unit: `SHiNE-agent-bot-coder/scripts/systemd/shine-agent-bot-coder.service`
- Скрипт установки: `SHiNE-agent-bot-coder/scripts/systemd/install-local-systemd.sh`
## Предусловия
1. Заполнен `.env` на основе `.env.example`.
2. Доступен рабочий Codex CLI:
- `/home/ai/.cache/JetBrains/IntelliJIdea2026.1/aia/codex/bin/codex-x86_64-unknown-linux-musl`
3. На машине установлен `systemd --user`.
## Установка
Из корня репозитория:
```bash
bash SHiNE-agent-bot-coder/scripts/systemd/install-local-systemd.sh
```
Скрипт:
1. проверяет наличие `python3`;
2. копирует unit в `~/.config/systemd/user/`;
3. делает `systemctl --user daemon-reload`;
4. включает автозапуск и стартует сервис.
## Проверка
```bash
systemctl --user status shine-agent-bot-coder --no-pager
journalctl --user -u shine-agent-bot-coder -f
```
## Перезапуск после изменений
```bash
systemctl --user restart shine-agent-bot-coder
```