Перейти к основному содержимому

Манифест плагина

Манифест — это файл dagstack.toml в корне папки плагина. Он декларирует метаданные плагина и требования к среде исполнения. Манифест — единственный источник истины для обнаружения: плагин без манифеста реестром не виден, даже если код корректен.

Минимальный манифест

plugins/my-plugin/dagstack.toml
[plugin]
name = "my-plugin"
kind = "tool"
runtime = "in_process"
core_version = ">=0.1.0,<1.0.0"

Этого достаточно для первой регистрации. Все опциональные поля — ниже.

Обязательные поля

ПолеТипОписание
nameстрокаИмя плагина, уникальное в пределах kind. Строчные буквы, цифры, дефис, нижнее подчёркивание.
kindстрокаВид плагина — какой контракт он реализует. Примеры: llm, vector_store, chunker, pipeline, tool, orchestrator.
runtimeстрока или массивИсполняющая среда: in_process, mcp_stdio, mcp_http. Допускается массив (плагин поддерживает несколько сред).
core_versionстрокаТребование к версии ядра dagstack-plugin-system, semver range.

Опциональные поля

Метаинформация

[plugin]
name = "qdrant"
kind = "vector_store"
runtime = "in_process"
core_version = ">=0.1.0,<1.0.0"
version = "1.2.0"
description = "Vector store adapter for Qdrant."
authors = ["Dagstack Contributors"]
homepage = "https://example.org/qdrant-plugin"
license = "Apache-2.0"

Возможности (capabilities)

Используется диспетчером CapabilityDispatcher для выбора подходящего плагина под запрос. Возможности — произвольные строковые идентификаторы, семантика определяется видом.

[plugin]
name = "semantic-chunker"
kind = "chunker"
runtime = "in_process"
core_version = ">=0.1.0,<1.0.0"
capabilities = ["treesitter", "python", "typescript", "go"]

Ресурсы

Плагин декларирует, какие системные ресурсы ему нужны. Реестр подставляет их через inject_resources перед вызовом setup.

[plugin]
name = "sha-tagger"
kind = "tool"
runtime = "in_process"
core_version = ">=0.1.0,<1.0.0"

[plugin.resources]
required = ["Clock", "Rng", "BlobStore"]

В тестах стандартные ресурсы заменяются детерминированными: SystemClockFrozenClock, RandomRngDeterministicRng, InMemoryBlobStore остаётся.

Единица работы

Для плагинов, участвующих в оркестрации (Dagster, Celery, k8s), декларируется единица работы — набор ключей партиционирования и ожидаемая модель исполнения.

[plugin]
name = "file-indexer"
kind = "pipeline"
runtime = "in_process"
core_version = ">=0.1.0,<1.0.0"
execution_model = "async" # стиль исполнения хуков (sync | async | thread_cpu_bound | process_cpu_bound)

[plugin.unit_of_work]
declared = true
partition_key = "repo_id"
idempotency_mode = "input_hash" # input_hash | output_hash | none
checkpointable = true
content_hash = ["tenant_id", "repo_id", "file_sha"]
примечание

execution_model — это стиль исполнения хуков плагина (sync/async/CPU-bound), не класс диспетчеризации. Класс диспетчеризации (singleton, broadcast_collect, chain, capability) объявляется в hookspec вида плагина — в поле dispatch: каждого хука. См. ADR-0004 и Классы диспетчеризации.

  • partition_keys — поля, по которым оркестратор параллелит работу.
  • idempotent — признак, что повторный запуск с тем же content_hash даст тот же результат (оркестратор может пропустить).
  • content_hash — перечень полей для вычисления ключа идемпотентности.

Поддерживаемые возможности диспетчера

[plugin]
name = "openai-embedder"
kind = "embedder"
runtime = "in_process"
core_version = ">=0.1.0,<1.0.0"
supports_languages = ["en", "ru"]
supports_mime_types = ["text/plain"]

[plugin.supports]
text = true
image = false
batch = true
streaming = false

Поля supports_* используются CapabilityDispatcher для отбора плагинов под конкретный запрос. Решение, использовать ли capability-dispatch для хуков вида, принимается в hookspec вида в поле dispatch: — не в манифесте плагина.

Размещение манифеста в pyproject.toml (Python)

Для Python-плагинов, распространяемых как пакеты, допускается размещать содержимое манифеста в секции [tool.dagstack.plugin] файла pyproject.toml. Это удобно для публикуемых на PyPI плагинов, чтобы не дублировать метаданные.

pyproject.toml
[project]
name = "dagstack-plugin-openai"
version = "0.1.0"

[tool.dagstack.plugin]
name = "openai_compatible"
kind = "llm"
runtime = "in_process"
core_version = ">=0.1.0,<1.0.0"

Приоритет: если у плагина есть и dagstack.toml, и [tool.dagstack.plugin] в pyproject.toml, используется dagstack.toml.

Валидация

Валидация выполняется автоматически при discover. Вручную валидировать отдельный манифест можно так:

from dagstack.plugin_system import load_manifest, assert_manifest_valid
from my_plugin import MyPlugin

manifest = load_manifest("plugins/my-plugin/dagstack.toml")
assert_manifest_valid(MyPlugin, manifest)

Несоответствие схеме выбрасывает ManifestInvalid с путём к файлу и описанием первой ошибки валидации.