surfaces/docs/api-contract.md
Mikhail Putilovskij 36730ae716 feat: implement core/ and platform/ with full test coverage
- platform/interface.py: PlatformClient Protocol + Pydantic models (User,
  MessageResponse, UserSettings) — no explicit session management, Master
  handles container lifecycle
- platform/mock.py: MockPlatformClient with simulated latency, [MOCK]
  responses, is_new correctly True only on first creation
- core/protocol.py: unified dataclasses for all events and responses
  (IncomingMessage/Command/Callback, OutgoingMessage/UI/Notification,
  AuthFlow, ChatContext, SettingsAction, etc.)
- core/store.py: StateStore Protocol + InMemoryStore (tests) + SQLiteStore
  (prod) with JSON serialization
- core/chat.py: ChatManager — chat metadata (C1/C2/C3), not container
  lifecycle (that's the platform's job)
- core/auth.py: AuthManager — start_flow / confirm / is_authenticated
- core/settings.py: SettingsManager — get/apply with store cache
- core/handler.py: EventDispatcher — registry-based routing with keys
  (command name, action name, attachment type, "*" catch-all)
- core/handlers/: register_all() + start/new/message/callback/settings
  handlers; voice slot falls back to stub text until voice_handler added
- conftest.py: sys.path fix so local platform/ shadows stdlib platform
- docs/api-contract.md: rewritten for Lambda Lab 3.0 container model

46 tests passing, 0 warnings.
2026-03-29 21:42:02 +03:00

3.9 KiB
Raw Permalink Blame History

API Contract — Lambda Platform

Статус: ЧЕРНОВИК — проектируем сами, уточняем с Азаматом когда SDK будет готов Последнее обновление: 2026-03-29


Архитектурный контекст

Каждому пользователю выделяется один LXC-контейнер с workspace 10 ГБ. Workspace содержит директории чатов: C1/, C2/, C3/ — файлы + history.db в каждом.

Master управляет lifecycle контейнера (запуск, заморозка, пробуждение). Бот не управляет lifecycle — он передаёт user_id + chat_id + сообщение. Master сам решает: нужно ли поднять контейнер, смонтировать нужный чат, запустить агента.


Base URL

https://api.lambda-platform.io/v1

Аутентификация

Authorization: Bearer {SERVICE_TOKEN}

Сервисный токен выдаётся команде поверхностей. Не путать с токеном пользователя.


Users

GET /users/{external_id}?platform={platform}

Получает или создаёт пользователя.

Query params:

  • platformtelegram | matrix

Response 200:

{
  "user_id": "usr_abc123",
  "external_id": "12345678",
  "platform": "telegram",
  "display_name": "Иван Иванов",
  "created_at": "2025-01-15T10:30:00Z",
  "is_new": false
}

Messages

Бот не управляет сессиями явно. Отправка сообщения — единственная операция. Master решает: нужен ли новый контейнер, или разбудить существующий.

POST /users/{user_id}/chats/{chat_id}/messages

Отправляет сообщение пользователя агенту. Master поднимает/размораживает контейнер, монтирует нужный чат (C1/, C2/...), запускает агента.

Request:

{
  "text": "Привет, что ты умеешь?",
  "attachments": []
}

Response 200:

{
  "message_id": "msg_qwe012",
  "response": "Я AI-агент Lambda...",
  "tokens_used": 142,
  "finished": true
}

Settings

GET /users/{user_id}/settings

Настройки пользователя: скиллы, коннекторы, SOUL, безопасность, план.

Response 200:

{
  "skills": {"web-search": true, "browser": false},
  "connectors": {"gmail": {"connected": true, "email": "user@gmail.com"}},
  "soul": {"name": "Лямбда", "style": "friendly"},
  "safety": {"email-send": true, "file-delete": true},
  "plan": {"name": "Beta", "tokens_used": 800, "tokens_limit": 1000}
}

POST /users/{user_id}/settings

Применяет действие над настройками.

Request:

{
  "action": "toggle_skill",
  "payload": {"skill": "browser", "enabled": true}
}

Response 200:

{"ok": true}

Error format

{
  "error": "ERROR_CODE",
  "message": "Human readable description",
  "details": {}
}

Коды ошибок: USER_NOT_FOUND, RATE_LIMITED, PLATFORM_ERROR, CONTAINER_UNAVAILABLE


Открытые вопросы к команде платфрмы (SDK)

  • Точный формат эндпоинта отправки сообщения — URL, поля
  • Как передавать вложения (файлы, изображения)? Через S3 pre-signed URL или напрямую?
  • Стриминговый ответ (SSE / WebSocket) или только sync?
  • Формат SettingsAction — совпадает с нашим или другой?