SDK pentru plugin-uri
Un plugin este descris de un singur manifest.json. Contractul care validează
manifestul în timpul dezvoltării este același pe care platforma îl impune la
momentul instalării, astfel încât un manifest care trece de validate este un
manifest pe care marketplace-ul îl va accepta. Interfața de linie de comandă
aihummer plugin acoperă întregul ciclu de viață: de la schelet la semnare și
publicare.
Un manifest, un contract
Un plugin are exact o sursă a adevărului — manifest.json-ul său. Acesta declară
tipul plugin-ului (kind), modul în care este configurat (config[]),
capabilitățile sale și — pentru serviciile native pe gazdă — pașii install[] și
comanda de pornire pe care le execută
SystemdDeployer. Deoarece dezvoltarea și
instalarea folosesc același contract de validare, „manifest valid” și „plugin
instalabil” înseamnă același lucru.
[!NOTE] Manifestul descrie contractul unui plugin, nu numele paginii sale de magazin.
slug-ul de mașină provine din numele directorului/pachetului (încărcare laterală privată) sau dintr-un câmp de trimitere (public) — consultă Publicarea unui plugin.
CLI
aihummer plugin grupează comenzile de dezvoltare, împachetare și publicare:
# Scaffold a manifest (kind: connector | service | openapi | mcp)
aihummer plugin init <kind> [dir]
# Validate a manifest against the install contract
aihummer plugin validate <manifest.json>
# Generate an ed25519 author key (writes <prefix>.key and <prefix>.pub)
aihummer plugin keygen [--out <prefix>]
# Build and package the plugin into a release tarball + .sha256
aihummer plugin package <dir> [--out <file>] [--slug <slug>] [--build "<cmd>"]
# Sign the release identity (slug\0version\0source_ref); with --manifest the
# signature is embedded into the manifest.signature field
aihummer plugin sign --key <priv> [--manifest <m.json>] <bundle|dir>
# Upload a private plugin into your own instance (side-load)
aihummer plugin publish --private --instance <url> --token <admin> <bundle.tar.gz>
# Open a PR to the public 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>]
| Comandă | Ce face |
|---|---|
init <kind> [dir] |
Scrie un manifest.json inițial pentru tipul ales. |
validate <m.json> |
Validează manifestul cu același contract ca la instalare. |
keygen |
Generează perechea de chei a autorului: .key (privată, ține-o secretă) și .pub, afișează key id-ul. |
package <dir> |
Construiește (opțional --build) și împachetează în <slug>-<version>.tar.gz cu o structură --strip-components=1, scrie .sha256. Nu împachetează niciodată .env, *.key, node_modules, .git. |
sign --key <priv> |
Semnează identitatea de lansare; afișează semnătura și key id-ul; cu --manifest încorporează semnătura în manifest. |
publish --private |
Încarcă un pachet în POST /v1/admin/modules/upload al instanței tale. |
publish --public |
Deschide un PR către AiHummer/marketplace-catalog. |
Ambele moduri de publicare sunt detaliate pe Publicarea unui plugin.
Câmpurile manifestului
Faptul că un câmp este obligatoriu depinde de kind și de dacă plugin-ul este public. Câmpuri de bază și de identitate:
| Câmp | Tip | Obligatoriu | Scop |
|---|---|---|---|
kind |
string | întotdeauna | Tip: connector | service | openapi | mcp. |
version |
string | da | Versiunea plugin-ului (semver), de ex. 1.0.0. |
contract |
string | pentru canale | ID-ul contractului, de ex. aihummer.channel.v1. |
scope |
string | nu | Model de acces: shared (implicit) sau personal. |
capabilities |
string[] | nu | Capabilități declarate. |
config |
object[] | nu | Câmpurile formularului de configurare; fiecare are nevoie de key, plus label, secret, required. |
oauth |
object | nu | OAuth2 (authorize_url, token_url, scopes[]) pentru a conecta contul unui utilizator. |
signature |
string | când e semnat | semnătură ed25519 base64 peste identitatea de lansare (încorporată de sign). |
Câmpuri specifice tipului — exact un bloc este completat în funcție de kind:
| Câmp | Pentru kind | Obligatoriu | Scop |
|---|---|---|---|
host_native.exec_start |
connector, service | da | Comanda care rulează serviciul de lungă durată. |
host_native.runtime |
connector, service, mcp | nu | node | python | binary. |
host_native.install |
connector, service, mcp | nu | Pași de instalare (array de comenzi shell), rulați pe gazdă după extragere. |
host_native.port |
connector, service | nu | Portul TCP preferat (deployer-ul îl poate reatribui prin $PORT). |
host_native.health_path |
connector, service | nu | Calea de verificare a sănătății (implicit /healthz). |
openapi.spec_url |
openapi | da | URL-ul specificației OpenAPI 3.x. |
openapi.base_url |
openapi | nu | Suprascrie servers[0].url. |
openapi.allowed_hosts |
openapi | nu | Lista de permisiuni de ieșire pentru instrumentele sintetizate. |
openapi.auth |
openapi | nu | Mapează securityScheme → numele secretului. |
openapi.tool_prefix |
openapi | nu | Prefixul numelui instrumentului. |
mcp.transport |
mcp | da | stdio sau http. |
mcp.command / mcp.args |
mcp (stdio) | da pentru stdio | Executabilul serverului și argumentele. |
mcp.url |
mcp (http) | da pentru http | URL-ul endpoint-ului MCP. |
mcp.auth_header / mcp.secret_token_key |
mcp (http) | nu | Antetul și cheia secretă pentru token-ul bearer. |
Câmpurile paginii de magazin și de identitate (pentru plugin-uri publice)
Pentru a intra în catalogul public, un manifest trebuie să poarte identitatea editorului și câmpurile paginii de magazin. O încărcare laterală privată nu are nevoie de niciunul dintre acestea — un astfel de plugin este de încredere la nivelul instanței.
| Câmp | Tip | Obligatoriu | Scop |
|---|---|---|---|
visibility |
string | nu | public | private | unlisted. Gol = moștenit/propriu (fără cerință de identitate). |
publisher |
string | pentru public | Spațiul de nume al editorului, ^[a-z0-9][a-z0-9-]{1,38}$. Slug-urile publice se numesc @publisher/slug. |
publisher_key_id |
string | pentru public | key id-ul cheii cu care este semnat artefactul. |
description |
string | pentru public | Descrierea paginii de magazin din catalog. |
icon |
string | pentru public | Pictograma plugin-ului: un URL https:// sau un URI data:. |
screenshots |
string[] | nu | Capturi de ecran ale paginii de magazin (array de URL-uri https://; fiecare nevidă). |
[!TIP] Rulează
aihummer plugin validateînainte de fiecare publicare. Contractul de instalare și de validare sunt identice, astfel încât un manifest care trece local va fi acceptat atât de deployer-ul marketplace-ului, cât și de validatorul catalogului public.
Manifeste minimale
Un schelet service (ceea ce scrie 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 }
]
}
Un manifest openapi fără cod este chiar mai scurt — doar indică specificația:
{
"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 }
]
}
Un manifest mcp (transport 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"] }
}
De la manifest la marketplace
După validare, un plugin este împachetat (package), semnat (sign) și publicat
într-unul din două moduri:
- Privat (pentru tine) — încărcare laterală în instanța ta prin interfața de
administrare sau
publish --private. Artefactul nu părăsește niciodată instanța. - Public (pentru toți) —
publish --publicdeschide un PR către catalogul public; după recenzie, AiHummer contrasemnează lansarea și o publică în catalogul comunității.
Consultă Publicarea unui plugin pentru parcurgerea completă.
Unde mergi mai departe
- Publicarea unui plugin — încărcare laterală privată și registrul public, contractul de trimitere, moderarea.
- Integrări fără cod — tipurile
openapișimcpîn detaliu. - Instalare și actualizări — ce
conduce
install[], poarta de sănătate, încrederea și actualizările semnate. - Marketplace: prezentare generală și niveluri — unde se află fiecare tip și cum diferă catalogul oficial de cel al comunității.