Архитектура Cordis: плагины как базовый слой композиции современных JS/TS-приложений
Плагинные системы давно доказали жизнеспособность в экосистеме JavaScript. Сборщики Webpack и Vite построены на плагинах, Fastify организует серверные маршруты как дерево расширений, а редакторы кода предоставляют тысячи надстроек. Однако исторически плагины оставались внешним слоем: они расширяли инструмент разработки, тогда как само прикладное приложение строилось вокруг монолитного ядра с жесткими связями и ручным внедрением зависимостей.
Фреймворк Cordis и построенная на нем система DeepSeek Harness (DSH) предлагают архитектурный сдвиг: сделать концепцию «всё является плагином» основным принципом композиции самого приложения. В этой модели исчезает привилегированное бизнес-ядро, а среда выполнения превращается в оркестратор жизненного цикла, эффектов и зависимостей.
От расширяемого ядра к приложению из плагинов
В классической архитектуре существует четкая граница между ядром системы и расширениями:
- Ядро определяет ключевые сценарии, владеет базой данных, маршрутизацией и авторизацией;
- Плагины подключаются к выделенным точкам расширения (hooks) и решают второстепенные задачи.
Такая схема стабильна, пока система невелика. Но по мере роста продукта ядро превращается в узкое горлышко: изменение базового функционала требует правок монолита, провоцируя конфликты между командами.
В архитектуре Cordis привычное ядро отсутствует: приложение собирается целиком из равноправных плагинов. В проекте DeepSeek Harness плагинами являются адаптеры нейросетевых моделей, инструменты выполнения кода, журналы сессий, агентный цикл (agent loop) и пользовательский интерфейс.
Вместо монолитного ядра остается минимальная среда композиции (composition runtime). Ее задача — не диктовать бизнес-логику, а обеспечивать правила взаимодействия:
- Какие модули зарегистрированы в системе;
- Какие сервисы требуются модулю для запуска;
- Какие ресурсы плагин предоставляет окружению;
- Какими эффектами (подписками, таймерами, DOM-элементами) владеет компонент;
- Как корректно очистить состояние при отключении модуля.
| Параметр архитектуры | Расширяемое приложение | Приложение из плагинов (Cordis) |
|---|---|---|
| Роль ядра | Реализует всю основную логику | Минимальная среда композиции (runtime) |
| Статус плагина | Второстепенное дополнение | Базовый строительный блок системы |
| Точки интеграции | Жестко заданные хуки ядра | Свободная публикация и потребление сервисов |
| Управление эффектами | Ручная очистка слушателей | Автоматический откат при выгрузке контекста |
| Границы команд | Общий код ядра с конфликтами | Независимые изолированные модули |
Управление эффектами и пространственно-временная композируемость
Теоретической основой Cordis выступает концепция пространственно-временной композируемости (spatiotemporal composability). Она решает главную проблему модульных JavaScript-систем — утечки ресурсов и непредсказуемый порядок инициализации.
Пространственная изоляция достигается через иерархию контекстов (Context). Плагин не обращается к глобальным объектам: он получает изолированный контекст, через который регистрирует службы (Service) и декларирует требования к окружению. Плагин видит только те зависимости, которые явно объявлены в его контракте.
Временная согласованность гарантирует детерминированный жизненный цикл. В обычном приложении на Node.js разработчик обязан вручную отписываться от событий, закрывать сокеты и очищать таймеры при остановке модуля, иначе возникает утечка памяти.
В Cordis каждый плагин ассоциирован с внутренней структурой выполнения (fiber). Все созданные плагином ресурсы, события и дочерние контексты регистрируются средой выполнения. При отключении или перезагрузке плагина:
- Runtime останавливает обработку входящих событий плагина;
- Зарегистрированные плагином слушатели событий автоматически удаляются;
- Очищаются созданные таймеры, отменяются асинхронные задачи и закрываются соединения;
- Зависимые плагины переводятся в состояние ожидания или безопасно деактивируются.
Клиент и сервер: три механизма доставки плагинов
Архитектура Cordis работает как на сервере под Node.js, так и в браузере. Однако доставка модулей на клиентскую сторону создает вызов: браузер не имеет прямого доступа к файловой системе. Анализ проекта DeepSeek Harness выделяет три способа решения этой задачи:
- Виртуальные модули в общем графе сборки (Virtual Modules). Плагины сканируются сборщиком (Vite или Rollup) на этапе компиляции и объединяются в виртуальный реестр. Это дает строгую типизацию в TypeScript и высокую скорость. Недостаток — монолитный деплой: добавление плагина требует пересборки бандла.
- Module Federation. Технология сборщиков (Webpack, Rspack), позволяющая подгружать скомпилированные части приложения из независимых сетевых источников в рантайме. Команды могут независимо развертывать плагины на своих серверах. Платой за гибкость становится сложность согласования версий общих библиотек (shared dependencies).
- Клиентская модульная система DSH. В проекте DeepSeek Harness реализован собственный загрузчик, ориентированный на динамическую оркестрацию. Он принимает модули в изолированных контекстах, монтирует их в дерево Cordis и позволяет на лету активировать и выгружать функционал (например, панели для AI-агентов) без перезагрузки веб-страницы.
Параллели с микросервисами и Kubernetes
Плагинную композицию часто сравнивают с микросервисами, поскольку она позволяет независимым командам разрабатывать компоненты без блокировок в общем репозитории.
Однако еще более точная аналогия прослеживается с оркестрацией в Kubernetes:
- Декларативное управление состоянием: Плагин декларирует желаемое состояние системы (наличие сервиса, активные маршруты, обработчики сообщений).
- Цикл согласования (Reconciliation Loop): При изменении состава плагинов среда выполнения динамически перестраивает граф зависимостей, запуская готовые модули и приостанавливая те, чьи зависимости временно недоступны.
- Жизненный цикл подов: Включение и отключение плагина с автоматической очисткой побочных эффектов внутри одного процесса напоминает создание и удаление контейнеров на узле кластера.
Cordis реализует эти паттерны внутри единого процесса Node.js или вкладки браузера, избавляя систему от сетевых задержек и оверхеда на сериализацию данных.
Границы применимости: за что приходится платить
Превращение приложения в сеть взаимосвязанных плагинов несет инженерные компромиссы:
- Отсутствие изоляции памяти: Все плагины Cordis исполняются в общем адресном пространстве V8. Плагин с ошибкой или бесконечным синхронным циклом может заблокировать весь тред, а утечка глобальных объектов не устраняется средой автоматически. Плагины гарантируют изоляцию эффектов, но не изоляцию памяти.
- Накладные расходы на диспетчеризацию: Вызов методов через контексты, перехват событий и непрерывный обход графа зависимостей снижают предельную пропускную способность по сравнению с прямыми монолитными вызовами.
- Сложность отладки: Нелинейный граф взаимодействия затрудняет чтение стека ошибок. Стек-трейс проходит через служебные уровни среды композиции, скрывая исходную причину сбоя.
- Зрелость экосистемы: Фреймворк Cordis находится в стадии активного развития (релизы серии
4.0.0-rc), а его документация продолжает формироваться. API может претерпевать изменения между версиями.
Чеклист для архитектора: когда оправдана плагинная среда
Переход на компонентную архитектуру Cordis оправдан в следующих случаях:
- Продукт создается распределенными командами, которым необходимо вести разработку без блокировок в общем репозитории;
- В системе используются AI-агенты, динамически подключающие инструменты, контексты и навыки во время работы;
- Требуется горячая замена модулей без остановки сервера и перезагрузки интерфейса;
- Продукт проектируется как платформа, вокруг которой планируется развивать экосистему расширений.
Для небольших стабильных приложений со скромной функциональностью введение дополнительного слоя композиции создаст избыточную сложность без практической отдачи.
