Cluster · разработчикам
SDK в своём проекте
Установка · Первый модуль · Справочник методов
Устанавливаемый пакет cluster-sdk содержит публичные классы и конструкторы, объявления типов и команды работы с проектом. Ядро, серверный транспорт и служебные данные в пакет не входят. Рабочие app и loader передаёт Cluster при запуске модуля.
Подготовка проекта
python -m cluster_sdk init ./my-module --name "My module"Можно вызвать установленную команду cluster-sdk с теми же аргументами. Далее используется форма python -m cluster_sdk, чтобы команда точно выполнялась в выбранном окружении.
init создаёт main.py и manifest.json, только если обоих файлов ещё нет. Если один из них уже существует, шаблон не добавляется. Исходники пользователя и существующее описание версии не заменяются. Для готового проекта или папки с несколькими модулями используй python -m cluster_sdk init . --existing: шаблон не создаётся даже в пустой папке.
Команда создаёт или дополняет pyrightconfig.json и .vscode/settings.json. Сохраняются пользовательские параметры проверки и редактора; путь интерпретатора обновляется на Python, из которого вызвана команда. Для виртуального окружения также обновляются venvPath и venv. Перед изменением существующего JSON сохраняется файл *.before-cluster-sdk.json. Файл с комментариями или некорректным JSON не перезаписывается; команда сообщает, что его нужно проверить вручную.
В requirements-dev.txt сохраняется ссылка на установленную версию SDK с инструментом проверки типов. Существующий файл не заменяется. Это зависимости разработки, не requirements серверного модуля.
Если в stubPath лежат неизменённые объявления прежнего пакета cluster-sdk-types, команда переносит их в скрытую резервную папку. Редактор после этого использует объявления установленного SDK. Собственные или изменённые объявления сохраняются; команда сообщает о возможном перекрытии типов.
Проверка проекта
python -m cluster_sdk check ./my-module --typesПроверяются синтаксис включаемых в пакет Python-файлов, импорт main.py, наличие Module, описание команд и остальных обработчиков, поля настроек, страницы, повторы алиасов. Перед сравнением учитываются значения по умолчанию полей и обработчиков, которые дописывает сервер. Отсутствующий required и required: false не считаются разными настройками. В отчёте есть state, число Python-файлов и признак проверки типов.
Для проверки импорта передаются локальные app и loader. Создаётся экземпляр Module; методы init и обработчики не вызываются. Сетевые службы такого app не подключены к ядру. Попытка обратиться к ним завершается InvalidState, а не подставным успешным результатом.
Если Pyright установлен, команда также запускает его в окружении проекта. Аргумент --types требует его наличия; без этого аргумента отсутствие Pyright отмечается как types=false, а не как успешная проверка типов. При ошибке команда завершается с ненулевым кодом и выводит причину.
Проверка импорта выполняет обычный Python-код на компьютере разработчика. Она не является изолированной средой. Результат не заменяет серверную проверку прав, зависимостей, сборки, лимитов и поведения модуля в Cluster.
Сборка архива
python -m cluster_sdk pack ./my-moduleКоманда сначала выполняет проверку, затем создаёт dist/my-module-1.0.0.zip. Имя берётся из каталога проекта, версия из manifest.json. main.py и manifest.json находятся в корне архива. Дополнительные Python-файлы и обычные файлы данных сохраняют относительные пути.
Исключаются виртуальные окружения .venv и venv, Git, скрытые файлы, кеши Python и анализаторов, настройки редакторов, node_modules, dist, tests, pyproject.toml, pyrightconfig.json и requirements-dev.txt. Символические ссылки не упаковываются: команда возвращает ошибку с их именем.
Для другого пути используй --output ./module.zip. Выходной файл должен иметь расширение .zip. Готовый архив загружается через форму публикации; перед выпуском его можно проверить на сайте.
Публичные конструкторы
Конструкторы работают после обычного импорта установленного SDK:
from cluster_sdk import Canvas, Document, Field, Fields, Pages, Text
text = Text().bold("Cluster").line("Hello.")
value = Document({"count": 0}).increment("count")
fields = Fields().add("title", Field("string").default("Hello"))
pages = Pages[int]([101, 102, 103], size=2)
scene = Canvas(800, 400)
scene.rect("background", 0, 0, 800, 400, fill="#18151f")
scene.text("title", "Cluster", 24, 24, 600, 80)В примере создаются текст, документ, поля, страницы и описание картинки. Отправка сообщения или отрисовка картинки через Image Generator по-прежнему выполняется в Cluster через выданные модулю права.
Свой транспорт
Обычному модулю транспорт настраивать не нужно. Для собственной клиентской привязки или теста отдельного обращения есть Client:
from __future__ import annotations
from cluster_sdk import Client, JSON
async def request(path: str, data: dict[str, JSON]) -> JSON:
if path == "db/get" and data["key"] == "count": return 3
raise RuntimeError("No response is configured for " + path)
async def read() -> JSON:
client = Client(request)
return await client.db.get("count")Client(transport) принимает объект с асинхронным методом request(path: str, data: dict[str, JSON]) -> JSON либо асинхронную функцию с такой сигнатурой. Все привычные службы доступны через этот клиент. Client.request(path, **data) проверяет JSON-совместимость переданных данных и копирует результат транспорта. Ошибки транспорта передаются вызывающему коду. Некорректный транспорт вызывает TypeError, неподходящее JSON-значение вызывает TypeError или ValueError.
Transport является протоколом такого объекта. FunctionTransport(request) оборачивает асинхронную функцию и предоставляет метод request. Функция возвращает результат операции; специфические ответы службы, например telegram/request, сохраняют свою структуру ok/result/error.
Это интерфейс клиентской привязки, а не готовое подключение к произвольному юзерботу. Серверные проверки доступа остаются в Cluster; установкой SDK их обойти нельзя.