Plugin SDK
Плагин описывается одним manifest.json. Тот же контракт, что проверяет
манифест на этапе разработки, платформа применяет и на этапе установки, поэтому
манифест, прошедший validate, — это манифест, который примет маркетплейс. CLI
aihummer plugin покрывает весь цикл: от заготовки до подписи и публикации.
Один манифест, один контракт
У плагина ровно один источник истины — его manifest.json. Он объявляет, какой
это вид плагина (kind), как его настраивать (config[]), какие у него
возможности, и — для host-native сервисов — шаги install[] и команду запуска,
которые выполняет SystemdDeployer. Поскольку
разработка и установка используют один и тот же контракт валидации, «валидный
манифест» и «устанавливаемый плагин» означают одно и то же.
[!NOTE] Манифест описывает контракт плагина, а не его витринное имя. Машинный
slugберётся из имени директории/бандла (private side-load) или из поля сабмишна (public) — см. Публикация плагина.
CLI
aihummer plugin объединяет команды разработки, упаковки и публикации:
# Создать заготовку манифеста (kind: connector | service | openapi | mcp)
aihummer plugin init <kind> [dir]
# Проверить манифест против контракта установки
aihummer plugin validate <manifest.json>
# Сгенерировать ed25519-ключ автора (пишет <prefix>.key и <prefix>.pub)
aihummer plugin keygen [--out <prefix>]
# Собрать и упаковать плагин в релизный tarball + .sha256
aihummer plugin package <dir> [--out <file>] [--slug <slug>] [--build "<cmd>"]
# Подписать релизную идентичность (slug\0version\0source_ref); с --manifest
# подпись встраивается в поле manifest.signature
aihummer plugin sign --key <priv> [--manifest <m.json>] <bundle|dir>
# Загрузить приватный плагин в свой инстанс (side-load)
aihummer plugin publish --private --instance <url> --token <admin> <bundle.tar.gz>
# Открыть PR в публичный каталог AiHummer/marketplace-catalog
aihummer plugin publish --public --dir <dir> --key <priv> \
--artifact-url <url> --publisher <name> \
--description <text> --icon <url> [--screenshot <url> ...] \
[--channel stable|beta] [--register-key <pub>]
| Команда | Что делает |
|---|---|
init <kind> [dir] | Пишет стартовый manifest.json под выбранный вид. |
validate <m.json> | Проверяет манифест тем же контрактом, что и установка. |
keygen | Генерирует пару ключей автора: .key (приватный, держите в секрете) и .pub, печатает key id. |
package <dir> | Собирает (опц. --build) и пакует в <slug>-<version>.tar.gz с раскладкой --strip-components=1, пишет .sha256. Никогда не пакует .env, *.key, node_modules, .git. |
sign --key <priv> | Подписывает релизную идентичность; печатает подпись и key id; с --manifest встраивает подпись в манифест. |
publish --private | Загружает бандл в POST /v1/admin/modules/upload своего инстанса. |
publish --public | Открывает PR в AiHummer/marketplace-catalog. |
Подробности обоих режимов публикации — на странице Публикация плагина.
Поля манифеста
Обязательность поля зависит от вида (kind) и от того, публичный ли это
плагин. Базовые и идентификационные поля:
| Поле | Тип | Обязательно | Назначение |
|---|---|---|---|
kind | string | всегда | Вид: connector | service | openapi | mcp. |
version | string | да | Версия плагина (semver), напр. 1.0.0. |
contract | string | для каналов | ID контракта, напр. aihummer.channel.v1. |
scope | string | нет | Модель доступа: shared (по умолчанию) или personal. |
capabilities | string[] | нет | Заявленные возможности. |
config | object[] | нет | Поля формы настройки; у каждого обязателен key, плюс label, secret, required. |
oauth | object | нет | OAuth2 (authorize_url, token_url, scopes[]) для подключения аккаунта пользователя. |
signature | string | для подписи | base64 ed25519-подпись релизной идентичности (встраивает sign). |
Поля по виду — ровно одно из блоков заполняется в зависимости от kind:
| Поле | Для вида | Обязательно | Назначение |
|---|---|---|---|
host_native.exec_start | connector, service | да | Команда запуска долгоживущего сервиса. |
host_native.runtime | connector, service, mcp | нет | node | python | binary. |
host_native.install | connector, service, mcp | нет | Шаги установки (массив shell-команд), выполняются на хосте после распаковки. |
host_native.port | connector, service | нет | Предпочтительный TCP-порт (deployer может переназначить через $PORT). |
host_native.health_path | connector, service | нет | Путь health-check (по умолчанию /healthz). |
openapi.spec_url | openapi | да | URL спецификации OpenAPI 3.x. |
openapi.base_url | openapi | нет | Переопределение servers[0].url. |
openapi.allowed_hosts | openapi | нет | Egress-allowlist для синтезированных инструментов. |
openapi.auth | openapi | нет | Маппинг securityScheme → имя секрета. |
openapi.tool_prefix | openapi | нет | Префикс имён инструментов. |
mcp.transport | mcp | да | stdio или http. |
mcp.command / mcp.args | mcp (stdio) | да для stdio | Исполняемый файл сервера и аргументы. |
mcp.url | mcp (http) | да для http | URL MCP-эндпоинта. |
mcp.auth_header / mcp.secret_token_key | mcp (http) | нет | Заголовок и ключ секрета для bearer-токена. |
Поля витрины и идентичности (для публичных плагинов)
Чтобы плагин попал в публичный каталог, манифест должен нести идентичность издателя и витринные поля. Для приватного side-load они не требуются — такой плагин доверяется на уровне инстанса.
| Поле | Тип | Обязательно | Назначение |
|---|---|---|---|
visibility | string | нет | public | private | unlisted. Пусто = legacy/первопартийный (без требования идентичности). |
publisher | string | для public | Namespace издателя, ^[a-z0-9][a-z0-9-]{1,38}$. Публичные слаги именуются @publisher/slug. |
publisher_key_id | string | для public | key id ключа, которым подписан артефакт. |
description | string | для public | Текст витрины (блурб) в каталоге. |
icon | string | для public | Иконка плагина: https://-URL или data:-URI. |
screenshots | string[] | нет | Скриншоты витрины (массив https://-URL; каждый непустой). |
[!TIP] Запускайте
aihummer plugin validateперед каждой публикацией. Контракт установки и валидации идентичен, поэтому манифест, прошедший проверку локально, примет и deployer маркетплейса, и валидатор публичного каталога.
Минимальные манифесты
Заготовка вида service (то, что пишет aihummer plugin init service):
{
"version": "1.0.0",
"kind": "service",
"scope": "shared",
"contract": "aihummer.channel.v1",
"host_native": {
"runtime": "node",
"install": ["npm ci --omit=dev"],
"exec_start": "node dist/main.js",
"port": 8800,
"health_path": "/healthz"
},
"config": [
{ "key": "api_token", "label": "API token", "secret": true, "required": true }
]
}
Манифест zero-code вида openapi ещё короче — он просто указывает на спецификацию:
{
"version": "1.0.0",
"kind": "openapi",
"scope": "shared",
"openapi": {
"spec_url": "https://api.example.com/openapi.json",
"tool_prefix": "example_",
"allowed_hosts": ["api.example.com"],
"auth": { "bearerAuth": "api_token" }
},
"config": [
{ "key": "api_token", "label": "API token", "secret": true, "required": true }
]
}
Манифест вида mcp (stdio-транспорт):
{
"version": "1.0.0",
"kind": "mcp",
"scope": "shared",
"host_native": { "runtime": "node", "install": ["npm ci --omit=dev"] },
"mcp": { "transport": "stdio", "command": "node", "args": ["server.js"] }
}
От манифеста к маркетплейсу
После валидации плагин упаковывается (package), подписывается (sign) и
публикуется в одном из двух режимов:
- Приватно (для себя) — side-load в свой инстанс через Admin UI или
publish --private. Артефакт не покидает инстанс. - Публично (для всех) —
publish --publicоткрывает PR в публичный каталог; после ревью AiHummer контрподписывает релиз и публикует его в community-каталог.
Полный разбор — на странице Публикация плагина.
Куда дальше
- Публикация плагина — private side-load и public registry, контракт сабмишна, модерация.
- Zero-code интеграции — виды
openapiиmcpподробно. - Установка и обновления — что приводят в
действие
install[], health-гейт, доверие и подписанные обновления. - Маркетплейс: обзор и тиры — где находится каждый вид и чем official-каталог отличается от community.