init: surfaces-bot — Telegram & Matrix prototype
- Surface Protocol: unified IncomingMessage/OutgoingUI/ChatContext - Telegram: Forum Topics (group + topics per chat) - Matrix: Space + rooms per chat - MockPlatformClient with PlatformClient Protocol - docs: surface-protocol, telegram/matrix specs, api-contract, claude-code-guide - project scaffold: src/, tests/, pyproject.toml Co-Authored-By: Claude Sonnet 4-6 <noreply@anthropic.com>
This commit is contained in:
commit
b6df29bd9b
29 changed files with 2504 additions and 0 deletions
150
docs/api-contract.md
Normal file
150
docs/api-contract.md
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
# API Contract — Lambda Platform
|
||||
|
||||
> **Статус:** ЧЕРНОВИК — проектируем сами, не ждём SDK
|
||||
> **Автор:** @architect
|
||||
> **Последнее обновление:** заполнить дату
|
||||
|
||||
Это описание того, что нам нужно от платформы.
|
||||
`MockPlatformClient` реализует этот контракт. При подключении реального SDK — только он меняется.
|
||||
|
||||
---
|
||||
|
||||
## Base URL
|
||||
|
||||
```
|
||||
https://api.lambda-platform.io/v1
|
||||
```
|
||||
|
||||
## Аутентификация
|
||||
|
||||
```
|
||||
Authorization: Bearer {SERVICE_TOKEN}
|
||||
```
|
||||
|
||||
Сервисный токен выдаётся команде поверхностей. Не путать с токеном пользователя.
|
||||
|
||||
---
|
||||
|
||||
## Users
|
||||
|
||||
### GET /users/{external_id}?platform={platform}
|
||||
Получает или создаёт пользователя.
|
||||
|
||||
**Query params:**
|
||||
- `platform` — `telegram` | `matrix`
|
||||
|
||||
**Response 200:**
|
||||
```json
|
||||
{
|
||||
"user_id": "usr_abc123",
|
||||
"external_id": "12345678",
|
||||
"platform": "telegram",
|
||||
"display_name": "Иван Иванов",
|
||||
"created_at": "2025-01-15T10:30:00Z",
|
||||
"is_new": false
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sessions
|
||||
|
||||
### POST /sessions
|
||||
Создаёт новую сессию с AI-агентом.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"user_id": "usr_abc123",
|
||||
"platform": "telegram",
|
||||
"context": {}
|
||||
}
|
||||
```
|
||||
|
||||
**Response 201:**
|
||||
```json
|
||||
{
|
||||
"session_id": "ses_xyz789",
|
||||
"agent_id": "agt_def456",
|
||||
"created_at": "2025-01-15T10:30:00Z",
|
||||
"expires_at": "2025-01-16T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### GET /sessions/{session_id}
|
||||
Получает информацию о сессии.
|
||||
|
||||
**Response 200:** — см. структуру выше + поле `status: "active" | "closed"`
|
||||
**Response 404:** `{"error": "SESSION_NOT_FOUND", "message": "..."}`
|
||||
|
||||
### DELETE /sessions/{session_id}
|
||||
Завершает сессию.
|
||||
|
||||
**Response 200:**
|
||||
```json
|
||||
{"closed": true}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Messages
|
||||
|
||||
### POST /sessions/{session_id}/messages
|
||||
Отправляет сообщение и получает ответ агента.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"text": "Привет, что ты умеешь?",
|
||||
"attachments": []
|
||||
}
|
||||
```
|
||||
|
||||
**Response 200:**
|
||||
```json
|
||||
{
|
||||
"message_id": "msg_qwe012",
|
||||
"response": "Я AI-агент Lambda...",
|
||||
"tokens_used": 142,
|
||||
"finished": true
|
||||
}
|
||||
```
|
||||
|
||||
### GET /sessions/{session_id}/messages?limit=20&offset=0
|
||||
История сообщений сессии.
|
||||
|
||||
**Response 200:**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"message_id": "msg_qwe012",
|
||||
"user_text": "Привет",
|
||||
"response": "Привет!",
|
||||
"tokens_used": 42,
|
||||
"created_at": "2025-01-15T10:31:00Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error format
|
||||
|
||||
Все ошибки возвращаются в едином формате:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "ERROR_CODE",
|
||||
"message": "Human readable description",
|
||||
"details": {}
|
||||
}
|
||||
```
|
||||
|
||||
Коды ошибок: `SESSION_NOT_FOUND`, `USER_NOT_FOUND`, `RATE_LIMITED`, `PLATFORM_ERROR`
|
||||
|
||||
---
|
||||
|
||||
## TODO (открытые вопросы к команде платформы)
|
||||
|
||||
- [ ] Нужна ли стриминговая передача ответа (SSE / WebSocket)?
|
||||
- [ ] Как обрабатываются вложения (изображения, файлы)?
|
||||
0
docs/architecture/.gitkeep
Normal file
0
docs/architecture/.gitkeep
Normal file
292
docs/claude-code-guide.md
Normal file
292
docs/claude-code-guide.md
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
# Гайд по Claude Code для разработки surfaces-bot
|
||||
|
||||
## Что такое Claude Code
|
||||
|
||||
Claude Code — это CLI-инструмент который запускается в терминале внутри твоего
|
||||
проекта. Он читает файлы, пишет код, запускает команды. Главное отличие от
|
||||
чата — он видит весь проект и действует автономно.
|
||||
|
||||
Запускается так:
|
||||
```bash
|
||||
cd surfaces-bot
|
||||
claude "твоя задача"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Агенты и когда их использовать
|
||||
|
||||
В проекте настроены специализированные агенты в `.claude/agents/`.
|
||||
Claude Code сам выбирает нужного если ты пишешь `@имя` в запросе.
|
||||
|
||||
| Агент | Когда | Пример |
|
||||
|---|---|---|
|
||||
| `@researcher` | Нужно разобраться как что-то работает | "как работает Forum Topics в aiogram?" |
|
||||
| `@architect` | Нужно принять архитектурное решение | "как хранить маппинг chat_id → room_id?" |
|
||||
| `@core-developer` | Писать core/ и platform/ | "реализуй core/protocol.py" |
|
||||
| `@tg-developer` | Писать Telegram-адаптер | "реализуй обработчик /start" |
|
||||
| `@matrix-developer` | Писать Matrix-адаптер | "реализуй создание Space" |
|
||||
| `@reviewer` | Проверить код перед PR | "проверь adapter/telegram/" |
|
||||
|
||||
---
|
||||
|
||||
## Базовые команды
|
||||
|
||||
### Простая задача (без агента)
|
||||
```bash
|
||||
# Небольшое изменение — быстрее без агента
|
||||
claude "добавь поле platform_user_id в ChatContext в core/protocol.py"
|
||||
```
|
||||
|
||||
### Задача через агента
|
||||
```bash
|
||||
# Агент читает нужную документацию сам
|
||||
claude "Use @tg-developer to implement adapter/telegram/handlers/auth.py
|
||||
based on docs/telegram-prototype.md auth flow"
|
||||
```
|
||||
|
||||
### Вопрос без изменений
|
||||
```bash
|
||||
claude "объясни как работает m.space.child в Matrix"
|
||||
# или просто интерактивно:
|
||||
claude # запускает интерактивный режим
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Параллельная разработка двух ботов
|
||||
|
||||
Главная идея: два терминала, два worktree, два агента одновременно.
|
||||
|
||||
### Шаг 1 — инициализация (один раз)
|
||||
```bash
|
||||
cd surfaces-bot
|
||||
git init
|
||||
git add . && git commit -m "init"
|
||||
|
||||
# Создать worktrees для адаптеров
|
||||
git worktree add .worktrees/telegram -b feat/telegram-adapter
|
||||
git worktree add .worktrees/matrix -b feat/matrix-adapter
|
||||
```
|
||||
|
||||
### Шаг 2 — сначала ядро (в main)
|
||||
```bash
|
||||
# В основной папке — core/ должен быть готов до адаптеров
|
||||
claude "Use @core-developer to implement core/protocol.py and platform/interface.py
|
||||
and platform/mock.py based on docs/surface-protocol.md and docs/api-contract.md"
|
||||
```
|
||||
Дождись — это фундамент. Остальное на нём строится.
|
||||
|
||||
### Шаг 3 — параллельно адаптеры (два терминала)
|
||||
|
||||
**Терминал 1:**
|
||||
```bash
|
||||
cd .worktrees/telegram
|
||||
claude "Use @tg-developer to implement the auth flow from docs/telegram-prototype.md.
|
||||
Start with adapter/telegram/handlers/auth.py and adapter/telegram/states.py"
|
||||
```
|
||||
|
||||
**Терминал 2 (одновременно):**
|
||||
```bash
|
||||
cd .worktrees/matrix
|
||||
claude "Use @matrix-developer to implement the auth flow from docs/matrix-prototype.md.
|
||||
Start with adapter/matrix/handlers/auth.py and adapter/matrix/space.py"
|
||||
```
|
||||
|
||||
Они работают в разных папках — не мешают друг другу.
|
||||
|
||||
### Шаг 4 — смёрджить когда готово
|
||||
```bash
|
||||
cd surfaces-bot # вернуться в main
|
||||
git merge feat/telegram-adapter
|
||||
git merge feat/matrix-adapter
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Экономия токенов (важно для Pro)
|
||||
|
||||
### Правило 1: Haiku для исследований
|
||||
```bash
|
||||
# @researcher использует Haiku — дёшево
|
||||
claude "Use @researcher to find examples of aiogram Forum Topics creation with code samples.
|
||||
Save findings to docs/research/telegram-forum-topics.md"
|
||||
|
||||
# НЕ делай так (Sonnet на простой вопрос — дорого):
|
||||
claude "Use @tg-developer to research how Forum Topics work"
|
||||
```
|
||||
|
||||
### Правило 2: точный контекст
|
||||
```bash
|
||||
# Хорошо — агент читает один конкретный файл
|
||||
claude "Use @tg-developer to implement adapter/telegram/keyboards/settings.py.
|
||||
Read docs/telegram-prototype.md section 'Настройки' for the button structure"
|
||||
|
||||
# Плохо — агент читает весь проект зря
|
||||
claude "Use @tg-developer to implement keyboards"
|
||||
# (агент начнёт читать всё подряд)
|
||||
```
|
||||
|
||||
### Правило 3: не запускай ревью на каждый коммит
|
||||
```bash
|
||||
# Ревью — только перед merge в main
|
||||
claude "Use @reviewer to review all changes in adapter/telegram/ before merging"
|
||||
# НЕ после каждого файла
|
||||
```
|
||||
|
||||
### Правило 4: маленькие задачи без агента
|
||||
```bash
|
||||
# Просто правка — без агента быстрее и дешевле
|
||||
claude "в adapter/telegram/keyboards/confirm.py замени текст кнопки с 'Да' на '✅ Подтвердить'"
|
||||
```
|
||||
|
||||
### Правило 5: не больше двух Sonnet одновременно
|
||||
```bash
|
||||
# Можно (Haiku + Sonnet):
|
||||
# Терминал 1: claude "Use @researcher ..." ← Haiku
|
||||
# Терминал 2: claude "Use @tg-developer ..." ← Sonnet
|
||||
|
||||
# Можно (два Sonnet в разных worktrees):
|
||||
# Терминал 1: cd .worktrees/telegram && claude "Use @tg-developer ..."
|
||||
# Терминал 2: cd .worktrees/matrix && claude "Use @matrix-developer ..."
|
||||
|
||||
# Слишком много (три Sonnet):
|
||||
# Терминал 1: claude "Use @core-developer ..."
|
||||
# Терминал 2: claude "Use @tg-developer ..."
|
||||
# Терминал 3: claude "Use @matrix-developer ..." ← стоп, подожди
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Типичные сценарии с примерами
|
||||
|
||||
### Сценарий А: начало с нуля
|
||||
|
||||
```bash
|
||||
# 1. Исследование (Haiku, дёшево)
|
||||
claude "Use @researcher to find matrix-nio examples of Space creation and room management.
|
||||
Save to docs/research/matrix-spaces.md"
|
||||
|
||||
# 2. Уточнение архитектуры (если что-то неясно)
|
||||
claude "Use @architect to clarify: should ConfirmationRequest timeout be handled in
|
||||
core/handler.py or in each adapter separately? Update docs/surface-protocol.md"
|
||||
|
||||
# 3. Ядро
|
||||
claude "Use @core-developer to implement core/protocol.py based on docs/surface-protocol.md"
|
||||
claude "Use @core-developer to implement core/session.py and core/auth.py"
|
||||
claude "Use @core-developer to implement platform/interface.py and platform/mock.py
|
||||
based on docs/api-contract.md"
|
||||
|
||||
# 4. Адаптеры параллельно (два терминала)
|
||||
# T1: claude "Use @tg-developer to implement auth flow in adapter/telegram/"
|
||||
# T2: claude "Use @matrix-developer to implement auth flow in adapter/matrix/"
|
||||
```
|
||||
|
||||
### Сценарий Б: добавить новую фичу в оба бота
|
||||
|
||||
Например, команда `!status` / `/status`:
|
||||
|
||||
```bash
|
||||
# 1. Убедиться что в core есть нужные структуры
|
||||
claude "Use @architect to check if StatusRequest is needed in core/protocol.py
|
||||
or can reuse existing structures. Read docs/surface-protocol.md"
|
||||
|
||||
# 2. Добавить в core если нужно
|
||||
claude "Use @core-developer to add status handling in core/handler.py"
|
||||
|
||||
# 3. Оба адаптера параллельно
|
||||
# T1: claude "Use @tg-developer to implement /status command in
|
||||
# adapter/telegram/handlers/settings.py"
|
||||
# T2: claude "Use @matrix-developer to implement !status command in
|
||||
# adapter/matrix/handlers/settings.py"
|
||||
```
|
||||
|
||||
### Сценарий В: что-то сломалось
|
||||
|
||||
```bash
|
||||
# Диагностика — без агента, просто спроси
|
||||
claude "pytest tests/adapter/telegram/test_auth.py провалился с ошибкой:
|
||||
AttributeError: 'NoneType' has no attribute 'session_id'
|
||||
Посмотри core/session.py и adapter/telegram/handlers/auth.py и скажи в чём причина"
|
||||
|
||||
# Починить точечно
|
||||
claude "в core/session.py метод get_session возвращает None если сессия не найдена,
|
||||
но в adapter/telegram/handlers/auth.py это не обрабатывается — исправь"
|
||||
```
|
||||
|
||||
### Сценарий Г: ревью перед merge
|
||||
|
||||
```bash
|
||||
# Запускать только когда фича готова
|
||||
cd .worktrees/telegram
|
||||
claude "Use @reviewer to review all files changed in this worktree (adapter/telegram/).
|
||||
Check against docs/telegram-prototype.md and docs/surface-protocol.md"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Интерактивный режим
|
||||
|
||||
Когда нужно работать итеративно — запусти без задачи:
|
||||
|
||||
```bash
|
||||
cd surfaces-bot
|
||||
claude
|
||||
```
|
||||
|
||||
Откроется REPL. Можно:
|
||||
```
|
||||
> покажи структуру core/protocol.py
|
||||
> добавь поле metadata в IncomingMessage
|
||||
> запусти pytest и покажи результат
|
||||
> что изменилось в последних 3 коммитах?
|
||||
```
|
||||
|
||||
Полезно когда задача неясная или нужно исследовать.
|
||||
|
||||
---
|
||||
|
||||
## Флаги которые пригодятся
|
||||
|
||||
```bash
|
||||
# Работать в конкретном worktree
|
||||
cd .worktrees/telegram && claude "..."
|
||||
|
||||
# Не трогать файлы, только смотреть (безопасно)
|
||||
claude --no-write "объясни как работает converter.py"
|
||||
|
||||
# Продолжить предыдущую сессию
|
||||
claude --continue
|
||||
|
||||
# Запустить с конкретной моделью (если хочешь Haiku без @researcher)
|
||||
claude --model claude-haiku-4-5-20251001 "быстрый вопрос про aiogram"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Частые ошибки
|
||||
|
||||
**Агент начал читать весь проект** → прерви (Ctrl+C), переформулируй точнее:
|
||||
```bash
|
||||
# Плохо
|
||||
claude "Use @tg-developer to implement settings"
|
||||
|
||||
# Хорошо
|
||||
claude "Use @tg-developer to implement adapter/telegram/keyboards/settings.py —
|
||||
кнопки главного меню настроек из docs/telegram-prototype.md раздел 'Главное меню настроек'"
|
||||
```
|
||||
|
||||
**Агент пишет не в ту папку** → явно укажи путь:
|
||||
```bash
|
||||
claude "Use @matrix-developer to create adapter/matrix/space.py with SpaceManager class"
|
||||
```
|
||||
|
||||
**Кончились токены в середине задачи** → задача сохраняется частично, продолжи:
|
||||
```bash
|
||||
claude --continue "продолжи реализацию, остановился на методе create_chat"
|
||||
```
|
||||
|
||||
**Агент предлагает архитектурное решение вместо кода** → перенаправь:
|
||||
```bash
|
||||
claude "Use @architect to decide: [вопрос]. После решения Use @tg-developer to implement it"
|
||||
```
|
||||
250
docs/matrix-prototype.md
Normal file
250
docs/matrix-prototype.md
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
# Matrix — описание прототипа
|
||||
|
||||
## Концепция
|
||||
|
||||
Один бот, каждый чат — отдельная комната, все комнаты собраны в Space.
|
||||
|
||||
При первом входе бот создаёт для пользователя личное пространство (Space) —
|
||||
это как папка в Element. Внутри Space бот создаёт комнату для каждого нового
|
||||
чата с агентом. Пользователь видит аккуратную структуру: одно пространство,
|
||||
внутри — список чатов. История хранится нативно в Matrix — это часть протокола,
|
||||
ничего дополнительно делать не нужно.
|
||||
|
||||
Matrix выбран как внутренняя поверхность: команды лаборатории, тестировщики,
|
||||
разработчики скиллов. Поэтому UX здесь — про удобство работы, а не онбординг.
|
||||
|
||||
---
|
||||
|
||||
## Аутентификация
|
||||
|
||||
### Флоу
|
||||
1. Пользователь приглашает бота в личные сообщения или пишет в общей комнате
|
||||
2. Бот проверяет `@user:matrix.org` — есть ли аккаунт на платформе
|
||||
3. Если нет — бот отправляет одноразовый код или ссылку
|
||||
4. Пользователь подтверждает, платформа возвращает токен
|
||||
5. Бот сохраняет привязку `matrix_user_id → platform_user_id`
|
||||
|
||||
### В моке
|
||||
- Любой пользователь проходит аутентификацию автоматически
|
||||
- Бот отвечает: «Добро пожаловать, {display_name}. Создаю ваше пространство...»
|
||||
- Демонстрирует флоу без реальной платформы
|
||||
|
||||
---
|
||||
|
||||
## Чаты через Space + комнаты (вариант Б)
|
||||
|
||||
### Структура
|
||||
```
|
||||
Space: «Lambda — {display_name}»
|
||||
├── 📌 Настройки ← специальная комната для команд управления
|
||||
├── 💬 Чат 1 ← первый чат, создаётся автоматически
|
||||
├── 💬 Чат 2
|
||||
└── 💬 Исследование рынка ← пользователь сам называет
|
||||
```
|
||||
|
||||
### Создание Space
|
||||
При первом входе бот:
|
||||
1. Создаёт Space `Lambda — {display_name}`
|
||||
2. Создаёт комнату `Настройки` (закреплена вверху)
|
||||
3. Создаёт первую комнату-чат `Чат 1`
|
||||
4. Приглашает пользователя во все комнаты
|
||||
5. Пишет в `Чат 1` приветствие
|
||||
|
||||
### Управление чатами
|
||||
Команды работают в любой комнате Space:
|
||||
|
||||
| Команда | Действие |
|
||||
|---|---|
|
||||
| `!new` | Создать новый чат (новую комнату в Space) |
|
||||
| `!new Название` | Создать чат с именем |
|
||||
| `!rename Название` | Переименовать текущую комнату |
|
||||
| `!archive` | Вывести комнату из Space (не удалять) |
|
||||
| `!chats` | Показать список чатов |
|
||||
|
||||
### Создание нового чата
|
||||
1. Пользователь пишет `!new` или `!new Анализ конкурентов`
|
||||
2. Бот создаёт новую комнату в Space
|
||||
3. Приглашает пользователя
|
||||
4. Пишет приветствие и создаёт сессию на платформе
|
||||
5. Пользователь переходит в новую комнату — начинает диалог
|
||||
|
||||
### В моке
|
||||
- Space и комнаты создаются реально через matrix-nio
|
||||
- Сессии — через MockPlatformClient
|
||||
- История хранится в Matrix нативно
|
||||
|
||||
---
|
||||
|
||||
## Основной диалог
|
||||
|
||||
### Флоу сообщения
|
||||
1. Пользователь пишет текст в комнату-чат
|
||||
2. Бот показывает typing (m.typing event)
|
||||
3. Запрос уходит в платформу (MockPlatformClient)
|
||||
4. Бот отвечает в той же комнате
|
||||
|
||||
### Вложения
|
||||
- Файлы, изображения отправляются как Matrix media events
|
||||
- Бот принимает `m.file`, `m.image`, `m.audio`
|
||||
- Передаёт в платформу как `attachments` через `IncomingMessage`
|
||||
- В моке: подтверждение получения + заглушка-ответ
|
||||
|
||||
### Реакции как действия
|
||||
Matrix поддерживает реакции на сообщения (`m.reaction`).
|
||||
Используем это для подтверждения действий агента:
|
||||
|
||||
```
|
||||
Агент: Хочу отправить письмо на vasya@mail.ru
|
||||
Тема: «Отчёт за неделю»
|
||||
|
||||
👍 — подтвердить ❌ — отменить
|
||||
```
|
||||
|
||||
Пользователь ставит реакцию — бот обрабатывает. Нативно и удобно.
|
||||
|
||||
### Треды для длинных задач
|
||||
Если агент выполняет долгую задачу (deep research, генерация документа),
|
||||
бот создаёт тред от своего первого ответа и пишет промежуточные статусы туда.
|
||||
Основной чат не засоряется.
|
||||
|
||||
```
|
||||
Бот: Начинаю исследование по теме «AI агенты 2025» [→ в треде]
|
||||
└── Ищу источники... (1/4)
|
||||
└── Анализирую статьи... (2/4)
|
||||
└── Формирую отчёт... (3/4)
|
||||
└── Готово. Отчёт: [...]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Комната «Настройки»
|
||||
|
||||
Специальная комната для управления агентом. Закреплена вверху Space.
|
||||
Команды работают только здесь — не мешают диалогу в чатах.
|
||||
|
||||
### Коннекторы
|
||||
```
|
||||
!connectors — показать список
|
||||
!connect gmail — подключить Gmail (OAuth ссылка)
|
||||
!connect github — подключить GitHub
|
||||
!connect calendar — подключить Google Calendar
|
||||
!connect notion — подключить Notion
|
||||
!disconnect gmail — отключить
|
||||
```
|
||||
|
||||
Статус:
|
||||
```
|
||||
Коннекторы:
|
||||
✅ Gmail — подключён (user@gmail.com)
|
||||
❌ GitHub — не подключён → !connect github
|
||||
❌ Google Calendar — не подключён
|
||||
❌ Notion — не подключён
|
||||
```
|
||||
|
||||
В моке: OAuth ссылка-заглушка → «Подключено ✓»
|
||||
|
||||
### Скиллы
|
||||
```
|
||||
!skills — показать список
|
||||
!skill on browser — включить Browser Use
|
||||
!skill off browser — выключить
|
||||
```
|
||||
|
||||
Статус:
|
||||
```
|
||||
Скиллы:
|
||||
✅ web-search — поиск в интернете
|
||||
✅ fetch-url — чтение веб-страниц
|
||||
✅ email — чтение почты (требует Gmail)
|
||||
❌ browser — управление браузером
|
||||
❌ image-gen — генерация изображений
|
||||
❌ video-gen — генерация видео
|
||||
✅ files — работа с файлами
|
||||
❌ calendar — календарь (требует Google Calendar)
|
||||
```
|
||||
|
||||
В моке: состояние хранится локально.
|
||||
|
||||
### Личность агента
|
||||
```
|
||||
!soul — показать текущий SOUL.md
|
||||
!soul name Лямбда — задать имя агента
|
||||
!soul style brief — стиль: brief | friendly | formal
|
||||
!soul priority «разбирать почту утром» — приоритетная задача
|
||||
!soul reset — сбросить к дефолту
|
||||
```
|
||||
|
||||
В моке: SOUL.md генерируется и хранится локально, агент обращается по имени.
|
||||
|
||||
### Безопасность
|
||||
```
|
||||
!safety — показать настройки
|
||||
!safety on email-send — требовать подтверждение перед отправкой письма
|
||||
!safety off calendar-create — не спрашивать для создания событий
|
||||
```
|
||||
|
||||
Статус:
|
||||
```
|
||||
Подтверждение требуется для:
|
||||
✅ отправка письма
|
||||
✅ удаление файлов
|
||||
✅ публикация в соцсетях
|
||||
❌ создание события в календаре
|
||||
❌ поиск в интернете
|
||||
```
|
||||
|
||||
### Подписка
|
||||
```
|
||||
!plan — показать текущий план
|
||||
```
|
||||
|
||||
```
|
||||
Подписка: Beta (бесплатно)
|
||||
Токены этот месяц: 800 / 1000
|
||||
━━━━━━━━░░ 80%
|
||||
```
|
||||
|
||||
Заглушка, реализует другая команда.
|
||||
|
||||
### Статус и диагностика
|
||||
```
|
||||
!status — состояние агента и платформы
|
||||
!sessions — список активных сессий
|
||||
!whoami — текущий аккаунт платформы
|
||||
```
|
||||
|
||||
```
|
||||
Статус:
|
||||
Платформа: ✅ доступна
|
||||
Агент: ✅ активен (сессия #abc123)
|
||||
Аккаунт: user@lambda.lab
|
||||
Активных чатов: 3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## FSM состояния
|
||||
|
||||
```
|
||||
[Invite] → AuthPending → AuthConfirmed
|
||||
↓
|
||||
SpaceSetup → Idle (в комнате Настройки)
|
||||
↓
|
||||
[новая комната] → SessionCreated → Idle (в чате)
|
||||
↓
|
||||
ReceivingMessage → WaitingResponse → Idle
|
||||
↓
|
||||
WaitingReaction (confirm) → [✅/❌] → Idle
|
||||
↓
|
||||
LongTask → [тред со статусами] → Done → Idle
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Стек
|
||||
|
||||
- Python 3.11+
|
||||
- matrix-nio (async) — Matrix клиент
|
||||
- MockPlatformClient → `platform/interface.py`
|
||||
- structlog для логирования
|
||||
- SQLite для хранения `matrix_user_id → platform_user_id`, состояния скиллов, маппинга `chat_id → room_id`
|
||||
0
docs/research/.gitkeep
Normal file
0
docs/research/.gitkeep
Normal file
311
docs/surface-protocol.md
Normal file
311
docs/surface-protocol.md
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
# Surface Protocol — унификация поверхностей
|
||||
|
||||
## Идея
|
||||
|
||||
Любая поверхность (Telegram, Matrix, будущий Discord, голос, web) делает одно
|
||||
и то же: принимает события от пользователя и отправляет ответы обратно.
|
||||
|
||||
Разница только в том как событие выглядит снаружи: aiogram `Message`,
|
||||
matrix-nio `RoomMessageText`, Discord `Interaction`. Внутри — одно и то же.
|
||||
|
||||
Surface Protocol — это общий язык между адаптерами поверхностей и ядром.
|
||||
Адаптер конвертирует нативные события в протокольные структуры и обратно.
|
||||
Ядро работает только с протокольными структурами и ничего не знает о транспорте.
|
||||
|
||||
**Добавить новую поверхность = написать один адаптер-конвертер.**
|
||||
Ядро не трогается.
|
||||
|
||||
---
|
||||
|
||||
## Структура проекта
|
||||
|
||||
```
|
||||
surfaces-bot/
|
||||
core/
|
||||
protocol.py — все унифицированные структуры данных
|
||||
handler.py — логика: IncomingEvent → OutgoingEvent
|
||||
session.py — управление сессиями и чатами
|
||||
auth.py — AuthFlow
|
||||
settings.py — SettingsAction, управление настройками
|
||||
|
||||
adapter/
|
||||
telegram/ — aiogram адаптер
|
||||
converter.py — aiogram Event → IncomingEvent, OutgoingEvent → aiogram API
|
||||
bot.py — точка входа, роутер
|
||||
matrix/ — matrix-nio адаптер
|
||||
converter.py — matrix-nio Event → IncomingEvent, OutgoingEvent → Matrix API
|
||||
bot.py — точка входа, клиент
|
||||
_template.py — шаблон для новой поверхности
|
||||
|
||||
platform/
|
||||
interface.py — Protocol: PlatformClient
|
||||
mock.py — MockPlatformClient
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Входящие события (Incoming)
|
||||
|
||||
Всё что пользователь делает конвертируется в одно из трёх:
|
||||
|
||||
### IncomingMessage
|
||||
Обычное сообщение — текст, файл, голос.
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class IncomingMessage:
|
||||
user_id: str # "tg_123456" | "@user:matrix.org"
|
||||
platform: str # "telegram" | "matrix"
|
||||
chat_id: str # "C1" | "C2" — ID чата в воркспейсе платформы
|
||||
text: str
|
||||
attachments: list[Attachment]
|
||||
reply_to: str | None # message_id если это ответ на сообщение
|
||||
```
|
||||
|
||||
### IncomingCommand
|
||||
Команда управления — `/start`, `!new`, `/settings`.
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class IncomingCommand:
|
||||
user_id: str
|
||||
platform: str
|
||||
chat_id: str
|
||||
command: str # "start" | "new" | "settings" | "archive" ...
|
||||
args: list[str] # аргументы после команды
|
||||
```
|
||||
|
||||
### IncomingCallback
|
||||
Нажатие кнопки или реакции — подтверждение, переключение скилла.
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class IncomingCallback:
|
||||
user_id: str
|
||||
platform: str
|
||||
chat_id: str
|
||||
action: str # "confirm" | "cancel" | "toggle_skill" | "connect" ...
|
||||
payload: dict # {"skill": "browser"} | {"action_id": "abc123"} ...
|
||||
```
|
||||
|
||||
### Attachment
|
||||
Вложение, нормализованное из любого источника.
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class Attachment:
|
||||
type: str # "image" | "document" | "audio" | "video"
|
||||
url: str | None # ссылка если доступна
|
||||
content: bytes | None # содержимое если скачано
|
||||
filename: str | None
|
||||
mime_type: str | None
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Исходящие события (Outgoing)
|
||||
|
||||
Всё что ядро хочет показать пользователю:
|
||||
|
||||
### OutgoingMessage
|
||||
Ответ агента или системное сообщение.
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class OutgoingMessage:
|
||||
chat_id: str
|
||||
text: str
|
||||
parse_mode: str # "markdown" | "plain"
|
||||
attachments: list[Attachment]
|
||||
reply_to: str | None
|
||||
```
|
||||
|
||||
### OutgoingUI
|
||||
Интерактивные элементы — кнопки, меню, переключатели.
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class OutgoingUI:
|
||||
chat_id: str
|
||||
text: str
|
||||
buttons: list[UIButton]
|
||||
|
||||
@dataclass
|
||||
class UIButton:
|
||||
label: str
|
||||
action: str # action для IncomingCallback
|
||||
payload: dict
|
||||
style: str # "primary" | "danger" | "secondary"
|
||||
```
|
||||
|
||||
Telegram рендерит это как InlineKeyboard.
|
||||
Matrix рендерит как текст с описанием реакций или HTML-кнопки.
|
||||
|
||||
### OutgoingNotification
|
||||
Асинхронное уведомление — агент закончил долгую задачу.
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class OutgoingNotification:
|
||||
chat_id: str
|
||||
text: str
|
||||
level: str # "info" | "warning" | "success" | "error"
|
||||
```
|
||||
|
||||
### OutgoingTyping
|
||||
Индикатор что агент думает.
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class OutgoingTyping:
|
||||
chat_id: str
|
||||
is_typing: bool
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Жизненный цикл (Lifecycle)
|
||||
|
||||
Унифицированные события для управления чатами и подключением.
|
||||
|
||||
### ChatContext
|
||||
Состояние чата — общее для всех поверхностей.
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class ChatContext:
|
||||
chat_id: str # "C1" | "C2" — ID в воркспейсе платформы
|
||||
display_name: str # «Чат 1» | «Анализ рынка»
|
||||
platform: str
|
||||
surface_ref: str # room_id в Matrix | topic_id в Telegram
|
||||
session_id: str | None # активная сессия платформы
|
||||
created_at: datetime
|
||||
is_archived: bool
|
||||
```
|
||||
|
||||
### AuthFlow
|
||||
Флоу аутентификации — одинаков для всех поверхностей.
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class AuthFlow:
|
||||
user_id: str
|
||||
platform: str
|
||||
state: str # "pending" | "code_sent" | "confirmed" | "failed"
|
||||
platform_user_id: str | None
|
||||
```
|
||||
|
||||
### ConfirmationRequest
|
||||
Запрос подтверждения опасного действия — от агента к пользователю.
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class ConfirmationRequest:
|
||||
action_id: str
|
||||
chat_id: str
|
||||
description: str # «Отправить письмо на vasya@mail.ru»
|
||||
risk_level: str # "low" | "medium" | "high"
|
||||
expires_at: datetime
|
||||
```
|
||||
|
||||
Telegram показывает как Inline-кнопки.
|
||||
Matrix показывает как реакции 👍 / ❌.
|
||||
Ядро не знает как именно — только получает `IncomingCallback` с `action: "confirm"`.
|
||||
|
||||
---
|
||||
|
||||
## SettingsAction
|
||||
|
||||
Унифицированные действия в настройках — одинаковы для Telegram и Matrix.
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class SettingsAction:
|
||||
action: str # "connect" | "disconnect" | "toggle_skill" | ...
|
||||
payload: dict
|
||||
|
||||
# Примеры:
|
||||
SettingsAction(action="connect", payload={"service": "gmail"})
|
||||
SettingsAction(action="toggle_skill", payload={"skill": "browser", "enabled": True})
|
||||
SettingsAction(action="set_soul", payload={"field": "name", "value": "Лямбда"})
|
||||
SettingsAction(action="set_safety", payload={"trigger": "email-send", "enabled": True})
|
||||
```
|
||||
|
||||
Ядро обрабатывает `SettingsAction` одинаково. Откуда пришло — не важно.
|
||||
|
||||
---
|
||||
|
||||
## PaymentEvent
|
||||
|
||||
Заглушка для биллинга — реализует другая команда.
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class PaymentRequired:
|
||||
user_id: str
|
||||
reason: str # "limit_reached" | "feature_locked"
|
||||
current_plan: str
|
||||
```
|
||||
|
||||
Поверхность получила `PaymentRequired` → показала заглушку.
|
||||
Содержимое заглушки потом наполняет команда биллинга.
|
||||
|
||||
---
|
||||
|
||||
## Как написать новую поверхность
|
||||
|
||||
Скопируй `adapter/_template.py` и реализуй три метода:
|
||||
|
||||
```python
|
||||
class MySurfaceAdapter:
|
||||
|
||||
def parse_incoming(self, raw_event) -> IncomingMessage | IncomingCommand | IncomingCallback:
|
||||
"""Конвертировать нативное событие в протокольную структуру."""
|
||||
...
|
||||
|
||||
def render_outgoing(self, event: OutgoingMessage | OutgoingUI | OutgoingNotification) -> any:
|
||||
"""Конвертировать протокольную структуру в нативный формат."""
|
||||
...
|
||||
|
||||
async def send(self, rendered) -> None:
|
||||
"""Отправить нативным способом."""
|
||||
...
|
||||
```
|
||||
|
||||
Дальше подключи адаптер в точку входа и передай `core.handler.handle` как callback.
|
||||
Всё остальное уже работает.
|
||||
|
||||
---
|
||||
|
||||
## Что ядро даёт бесплатно
|
||||
|
||||
Любая новая поверхность получает без дополнительного кода:
|
||||
|
||||
- управление сессиями (создание, переключение, закрытие)
|
||||
- управление чатами (`ChatContext`)
|
||||
- аутентификацию (`AuthFlow`)
|
||||
- подтверждение действий (`ConfirmationRequest`)
|
||||
- все настройки (коннекторы, скиллы, SOUL, безопасность, подписка)
|
||||
- интеграцию с платформой через `PlatformClient`
|
||||
- обработку ошибок платформы
|
||||
|
||||
---
|
||||
|
||||
## Замена MockPlatformClient на реальный SDK
|
||||
|
||||
Вся работа с платформой идёт через `PlatformClient` протокол:
|
||||
|
||||
```python
|
||||
class PlatformClient(Protocol):
|
||||
async def get_or_create_user(self, user_id: str, platform: str) -> User: ...
|
||||
async def create_session(self, user_id: str, chat_id: str) -> Session: ...
|
||||
async def send_message(self, session_id: str, text: str, attachments: list) -> AgentResponse: ...
|
||||
async def close_session(self, session_id: str) -> None: ...
|
||||
async def get_chat_history(self, user_id: str, chat_id: str) -> list[Message]: ...
|
||||
async def get_settings(self, user_id: str) -> UserSettings: ...
|
||||
async def update_settings(self, user_id: str, action: SettingsAction) -> None: ...
|
||||
```
|
||||
|
||||
`MockPlatformClient` реализует этот протокол сейчас.
|
||||
Реальный SDK — тоже реализует этот протокол, заменяя один файл.
|
||||
Адаптеры поверхностей и ядро не меняются вообще.
|
||||
221
docs/telegram-prototype.md
Normal file
221
docs/telegram-prototype.md
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
# Telegram — описание прототипа
|
||||
|
||||
## Концепция
|
||||
|
||||
Один бот, несколько чатов через Topics в Forum-группе.
|
||||
|
||||
При первом запуске бот создаёт для пользователя персональную Forum-группу
|
||||
(супергруппу с включёнными темами). Каждый новый чат с агентом — отдельная тема
|
||||
внутри группы. Пользователь видит это как список чатов в одном месте.
|
||||
|
||||
Бот управляет группой от имени пользователя через Telegram Bot API:
|
||||
создаёт темы, переименовывает, архивирует.
|
||||
|
||||
---
|
||||
|
||||
## Аутентификация
|
||||
|
||||
### Флоу
|
||||
1. Пользователь пишет боту `/start`
|
||||
2. Бот проверяет — есть ли аккаунт на платформе привязанный к этому `tg_user_id`
|
||||
3. Если нет — бот отправляет одноразовую ссылку или код для входа
|
||||
4. Пользователь подтверждает, платформа возвращает токен сессии
|
||||
5. Бот сохраняет привязку `tg_user_id → platform_user_id`
|
||||
|
||||
### В моке
|
||||
- Любой пользователь проходит аутентификацию автоматически
|
||||
- Кнопка «Войти» → пауза 1 сек → «Вы вошли как {имя}»
|
||||
- Демонстрирует флоу без реальной платформы
|
||||
|
||||
---
|
||||
|
||||
## Чаты через Forum Topics (вариант В)
|
||||
|
||||
### Как это работает
|
||||
- Бот создаёт супергруппу с Topics для каждого нового пользователя
|
||||
- Каждый чат = отдельная тема (Topic) в этой группе
|
||||
- История хранится нативно в Telegram (в самой теме)
|
||||
- Переключение между чатами = переключение между темами
|
||||
|
||||
### Управление чатами
|
||||
Внутри каждой темы доступны команды:
|
||||
|
||||
| Команда | Действие |
|
||||
|---|---|
|
||||
| `/new` | Создать новый чат (новую тему) |
|
||||
| `/rename Название` | Переименовать текущий чат |
|
||||
| `/archive` | Архивировать текущий чат |
|
||||
| `/chats` | Показать список всех чатов |
|
||||
|
||||
### Создание нового чата
|
||||
1. Пользователь пишет `/new` или нажимает кнопку
|
||||
2. Бот спрашивает название (опционально, можно пропустить)
|
||||
3. Бот создаёт новую тему в группе: «Чат 1», «Чат 2» и т.д.
|
||||
4. Бот отправляет в новую тему приветствие и создаёт сессию на платформе
|
||||
|
||||
### В моке
|
||||
- Группа и темы создаются реально через Bot API
|
||||
- Сессии на платформе — через MockPlatformClient
|
||||
- История в темах хранится нативно в Telegram, ничего не нужно делать
|
||||
|
||||
---
|
||||
|
||||
## Основной диалог
|
||||
|
||||
### Флоу сообщения
|
||||
1. Пользователь пишет текст в тему
|
||||
2. Бот показывает `typing...`
|
||||
3. Запрос уходит в платформу (сейчас — MockPlatformClient)
|
||||
4. Бот отвечает текстом агента
|
||||
|
||||
### Вложения
|
||||
- Фото, документы, голосовые — передаются в платформу как `attachments`
|
||||
- В моке: бот подтверждает получение файла и возвращает заглушку-ответ
|
||||
- Форматы: PDF, изображения, текстовые файлы
|
||||
|
||||
### Подтверждение действий
|
||||
Если агент собирается выполнить потенциально опасное действие
|
||||
(отправить письмо, удалить файл, сделать запись в календарь):
|
||||
|
||||
```
|
||||
Агент хочет выполнить действие:
|
||||
📧 Отправить письмо на vasya@mail.ru
|
||||
Тема: «Отчёт за неделю»
|
||||
|
||||
[✅ Подтвердить] [❌ Отменить]
|
||||
```
|
||||
|
||||
Пользователь нажимает кнопку — действие выполняется или отменяется.
|
||||
В моке: кнопки работают, действие логируется, ответ-заглушка.
|
||||
|
||||
---
|
||||
|
||||
## Настройки
|
||||
|
||||
Доступны через `/settings` в любой теме или в главном меню бота.
|
||||
Реализованы как цепочка инлайн-кнопок.
|
||||
|
||||
### Главное меню настроек
|
||||
```
|
||||
⚙️ Настройки
|
||||
|
||||
[🔗 Коннекторы] [🧩 Скиллы]
|
||||
[🧠 Личность] [🔔 Уведомления]
|
||||
[🔒 Безопасность] [💳 Подписка]
|
||||
```
|
||||
|
||||
### Коннекторы
|
||||
Подключение внешних сервисов. Агент получает доступ через API Proxy,
|
||||
пароли пользователю вводить не нужно — только OAuth.
|
||||
|
||||
| Коннектор | Способ подключения |
|
||||
|---|---|
|
||||
| Gmail / Outlook | OAuth ссылка |
|
||||
| Google Calendar | OAuth ссылка |
|
||||
| GitHub | OAuth ссылка |
|
||||
| Notion | OAuth ссылка |
|
||||
| Telegram (читать каналы) | Уже подключён |
|
||||
|
||||
В моке: кнопка «Подключить» → ссылка-заглушка → «Подключено ✓»
|
||||
|
||||
### Скиллы
|
||||
Включение/выключение навыков агента.
|
||||
|
||||
```
|
||||
🧩 Скиллы
|
||||
|
||||
✅ Поиск в интернете
|
||||
✅ Чтение почты
|
||||
❌ Управление браузером
|
||||
❌ Генерация изображений
|
||||
❌ Работа с календарём
|
||||
✅ Работа с файлами
|
||||
❌ Генерация видео
|
||||
```
|
||||
|
||||
Каждый скилл — кнопка-переключатель. Нажал — включил/выключил.
|
||||
В моке: состояние хранится локально, платформа не вызывается.
|
||||
|
||||
### Личность агента (SOUL.md)
|
||||
Онбординг-анкета при первом входе, потом редактирование.
|
||||
|
||||
```
|
||||
🧠 Личность агента
|
||||
|
||||
Как зовут твоего агента?
|
||||
[_Лямбда_____________]
|
||||
|
||||
Что он должен делать в первую очередь?
|
||||
[_Разбирать почту_____]
|
||||
|
||||
Стиль общения:
|
||||
[Деловой] [Дружелюбный] [Краткий]
|
||||
```
|
||||
|
||||
В моке: данные сохраняются, агент обращается к пользователю по имени из настроек.
|
||||
|
||||
### Уведомления
|
||||
Когда агент выполнил долгую задачу — уведомление в Telegram.
|
||||
|
||||
```
|
||||
🔔 Уведомления
|
||||
|
||||
✅ Задача выполнена
|
||||
✅ Требуется подтверждение действия
|
||||
❌ Ежедневный дайджест
|
||||
❌ Напоминания из календаря
|
||||
```
|
||||
|
||||
В моке: уведомления отправляются через бот с задержкой (симуляция).
|
||||
|
||||
### Безопасность
|
||||
Какие действия требуют явного подтверждения.
|
||||
|
||||
```
|
||||
🔒 Безопасность
|
||||
|
||||
Всегда спрашивать перед:
|
||||
✅ Отправкой письма
|
||||
✅ Удалением файлов
|
||||
✅ Публикацией в соцсетях
|
||||
❌ Созданием события в календаре
|
||||
❌ Поиском в интернете
|
||||
```
|
||||
|
||||
### Подписка
|
||||
Заглушка — реализует другая команда.
|
||||
|
||||
```
|
||||
💳 Подписка
|
||||
|
||||
Текущий план: Beta (бесплатно)
|
||||
Токены: ████████░░ 800/1000
|
||||
|
||||
[Подробнее о планах]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## FSM состояния
|
||||
|
||||
```
|
||||
[Start] → AuthPending → AuthConfirmed
|
||||
↓
|
||||
GroupSetup → Idle
|
||||
↓
|
||||
ReceivingMessage → WaitingResponse → Idle
|
||||
↓
|
||||
ConfirmAction → [Confirmed/Cancelled] → Idle
|
||||
↓
|
||||
Settings → [подменю] → Idle
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Стек
|
||||
|
||||
- Python 3.11+
|
||||
- aiogram 3.x (Router, FSM, InlineKeyboard, Forum Topics API)
|
||||
- MockPlatformClient → `platform/interface.py`
|
||||
- structlog для логирования
|
||||
- SQLite для хранения `tg_user_id → platform_user_id` и состояния скиллов
|
||||
68
docs/user-flow.md
Normal file
68
docs/user-flow.md
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# User Flow — Lambda Bot
|
||||
|
||||
> **Статус:** ШАБЛОН — заполняет @architect после исследований
|
||||
> **Зависит от:** docs/research/telegram-flows.md, docs/research/competitor-ux.md
|
||||
|
||||
---
|
||||
|
||||
## Основной сценарий (happy path)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor User
|
||||
participant Bot as Telegram/Matrix Bot
|
||||
participant Platform as Lambda Platform
|
||||
|
||||
User->>Bot: /start
|
||||
Bot->>Platform: GET /users/{tg_id}?platform=telegram
|
||||
Platform-->>Bot: {user_id, is_new}
|
||||
|
||||
alt Новый пользователь
|
||||
Bot->>User: Приветствие + инструкция
|
||||
else Существующий пользователь
|
||||
Bot->>User: Добро пожаловать обратно
|
||||
end
|
||||
|
||||
User->>Bot: Любое сообщение
|
||||
Bot->>Platform: POST /sessions (создаём сессию)
|
||||
Platform-->>Bot: {session_id, agent_id}
|
||||
|
||||
loop Диалог
|
||||
User->>Bot: Сообщение
|
||||
Bot->>Platform: POST /sessions/{id}/messages
|
||||
Platform-->>Bot: {response}
|
||||
Bot->>User: Ответ агента
|
||||
end
|
||||
|
||||
User->>Bot: /end или таймаут
|
||||
Bot->>Platform: DELETE /sessions/{id}
|
||||
Bot->>User: Сессия завершена
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Состояния FSM (Telegram)
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Idle: /start
|
||||
|
||||
Idle --> InSession: любое сообщение
|
||||
InSession --> InSession: сообщение пользователя
|
||||
InSession --> Idle: /end
|
||||
|
||||
InSession --> Error: ошибка платформы
|
||||
Error --> Idle: /start
|
||||
Error --> InSession: retry
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Открытые вопросы
|
||||
|
||||
> Заполняет @researcher и @architect после исследований
|
||||
|
||||
- [ ] Как выглядит онбординг новых пользователей у конкурентов?
|
||||
- [ ] Нужна ли кнопка "Новая сессия" или сессия стартует автоматически?
|
||||
- [ ] Что показываем пока агент думает (typing indicator)?
|
||||
- [ ] Как обрабатываем timeout ответа от платформы?
|
||||
Loading…
Add table
Add a link
Reference in a new issue