Быстрый старт
dagstack/plugin-system — универсальный реестр плагинов для приложений любого домена, которым нужны подключаемые точки расширения. Типичные сценарии: источники данных, обработчики событий, notification-каналы, authentication-провайдеры, шаги пайплайна, интеграции с внешними системами. Плагины находятся в каталоге по манифестам, загружаются в реестр и вызываются через один из пяти классов диспетчеризации (singleton, broadcast-collect, broadcast-notify, chain, capability).
:::info Статус публикации Пакеты Python и TypeScript готовятся к публикации на PyPI и npmjs.org. Пока доступны из внутреннего репозитория. Go-реализация — в дорожной карте; в примерах ниже показана планируемая сигнатура. :::
Установка
:::warning Зрелость реализаций Полноценный runtime на сегодня есть только для Python. TypeScript — в разработке: опубликованы эмитируемые из спецификации константы и типы, runtime появится в следующих релизах. Go — в дорожной карте; примеры ниже показывают планируемую сигнатуру на основе language-agnostic спецификации (см. ADR-0001..0006). :::
- Python
- TypeScript
- Go
pip install dagstack-plugin-system
npm install @dagstack/plugin-system
go get go.dagstack.dev/plugin-system
Первый плагин
Минимальный рабочий плагин состоит из двух файлов в отдельной папке: манифеста dagstack.toml и модуля реализации.
Манифест плагина
Манифест декларирует вид (kind), имя, исполняющую среду (runtime) и совместимую версию ядра.
[plugin]
name = "echo"
kind = "tool"
runtime = "in_process"
core_version = ">=0.1.0,<1.0.0"
Реализация плагина
- Python
- TypeScript
- Go
from dagstack.plugin_system import PluginContext
class EchoPlugin:
"""Returns the input message wrapped under the `echoed` key.
Mirrors the canonical `examples/echo_plugin.EchoTool` shipped
with the binding. Both sync and async `setup` / `teardown` are
accepted by the registry; the published example uses sync.
"""
def setup(self, context: PluginContext) -> None:
self._ctx = context
def execute(self, args: dict) -> dict:
return {"echoed": args["msg"]}
def teardown(self) -> None:
self._ctx = None
:::warning TypeScript runtime ships in Phase 1
@dagstack/plugin-system@0.1.0-rc.2 exports only the spec-emitted types — VERSION, ToolV1, OrchestratorV1. The runtime (PluginRegistry, discover, dispatchers, contract suite) lands in Phase 1. Today: implement the kind contract against the published types, then host plugins through Python over mcp_stdio or wait for the Phase 1 release. See the TypeScript API reference for the planned shape.
:::
package echo
import (
"context"
pluginsystem "go.dagstack.dev/plugin-system"
)
type EchoPlugin struct{}
func (p *EchoPlugin) Unwrap() any { return p }
func (p *EchoPlugin) Setup(ctx context.Context, pluginCtx *pluginsystem.PluginContext) error {
return nil
}
func (p *EchoPlugin) Invoke(payload string) (string, error) {
return payload, nil
}
func (p *EchoPlugin) Teardown(ctx context.Context) error {
return nil
}
Обнаружение и загрузка реестра
Функция discover(path) рекурсивно сканирует каталог, находит все папки с dagstack.toml, валидирует манифесты и возвращает реестр с загруженными плагинами. Метод setup_all() выполняет инициализацию каждого плагина с учётом зависимостей между ними (топологическая сортировка).
- Python
- TypeScript
- Go
import asyncio
import logging
from dagstack.plugin_system import PluginContext, PluginRegistry
async def main() -> None:
registry = PluginRegistry()
registry.discover("plugins/")
ctx = PluginContext(
config={},
logger=logging.getLogger("app"),
registry=registry,
)
await registry.setup_all(ctx)
for manifest in registry.list_manifests():
print(manifest.kind, manifest.name)
await registry.teardown_all()
asyncio.run(main())
:::warning TypeScript runtime ships in Phase 1
@dagstack/plugin-system@0.1.0-rc.2 exports only the spec-emitted types — VERSION, ToolV1, OrchestratorV1. The runtime (PluginRegistry, discover, dispatchers, contract suite) lands in Phase 1. Today: implement the kind contract against the published types, then host plugins through Python over mcp_stdio or wait for the Phase 1 release. See the TypeScript API reference for the planned shape.
:::
ctx := context.Background()
entries, err := pluginsystem.Discover("plugins/")
if err != nil {
panic(err)
}
reg := pluginsystem.NewRegistry()
for _, entry := range entries {
plugin := buildPlugin(entry.Manifest) // user-defined factory
if err := reg.RegisterManifest(entry.Manifest, plugin); err != nil {
panic(err)
}
}
pluginCtx := &pluginsystem.PluginContext{
Logger: slog.Default(),
Registry: reg,
}
if err := reg.SetupAll(ctx, pluginCtx); err != nil {
panic(err)
}
defer reg.TeardownAll(ctx)
for _, m := range reg.ListManifests() {
fmt.Println(m.Kind, m.Name)
}
Вызов плагина
Плагины получают через реестр по сочетанию kind + name. Возвращённый объект — это прокси, который применяет правила диспетчеризации, инъекцию ресурсов и проверки контракта.
- Python
- TypeScript
- Go
echo = registry.get_plugin("tool", name="echo")
result = echo.execute({"msg": "hello"})
assert result == {"echoed": "hello"}
:::warning TypeScript runtime ships in Phase 1
@dagstack/plugin-system@0.1.0-rc.2 exports only the spec-emitted types — VERSION, ToolV1, OrchestratorV1. The runtime (PluginRegistry, discover, dispatchers, contract suite) lands in Phase 1. Today: implement the kind contract against the published types, then host plugins through Python over mcp_stdio or wait for the Phase 1 release. See the TypeScript API reference for the planned shape.
:::
p, err := reg.Resolve("echo")
if err != nil {
panic(err)
}
echo := p.Unwrap().(*echo.EchoPlugin)
result, _ := echo.Invoke("hello")
fmt.Println(result) // hello
Что дальше
Понятия — как устроены основные компоненты:
- Реестр плагинов, Манифест, Обнаружение — базовые объекты.
- Виды плагинов, Исполняющие среды, Диспетчеризация — архитектурные концепты.
- Ресурсы (Resources DI), Runtime-инварианты — поведение в разных средах.
Руководства — как решать типовые задачи:
- Как написать плагин, Конфигурация, Жизненный цикл.
- Тестирование плагинов, Зависимости, Классы диспетчеризации.
Справочник — точные таблицы для быстрого поиска:
Спецификация — нормативные архитектурные решения:
- Обзор, ADR-0001: Архитектура ядра, ADR-0002: Диспетчеризация и остальные.
Справочник API (генерация отложена до выхода реализаций в stable):
- Python, TypeScript (roadmap), Go (roadmap).