Документация
Плагины
Манифесты расширений, API-интерфейсы рабочего хоста, вспомогательные инструменты и отдельный контракт на установку плагина браузера.
Автоматически переведено с английского. Смотреть оригинал на английском
Выберите поверхность расширения
@cadcamfun/plugin-sdk определяет контракт рабочего плагина с помощью plugin.json манифест и версия API 1. Его хост предоставляет службы, контролируемые возможностями, и запускает функции плагинов в рабочих процессах Bun. Загрузчик производственного помощника в настоящее время принимает плагины, которые запрашивают только ai:tool.
The /api/plugins Семейство HTTP использует другой контракт плагина браузера: ZIP-пакеты с manifest.json, a main запись, разрешения браузера, конфигурация и загрузка JavaScript. Установка пакета через этот API не делает его рабочим плагином SDK. Используйте манифест и жизненный цикл, соответствующие предполагаемой интеграции.
Манифест рабочего SDK
{
"id": "com.example.shop-helper",
"name": "Shop helper",
"version": "1.0.0",
"apiVersion": "1",
"entry": "index.js",
"capabilities": ["ai:tool"],
"contributes": {
"aiTools": [{
"id": "lookup",
"description": "Look up the shop's documented inspection checklist.",
"kind": "read",
"parameters": { "type": "object", "properties": {} },
"entry": "lookup"
}]
}
} Идентификаторы используют форму обратного DNS, версия является семантической. major.minor.patch с дополнительной предварительной версией и apiVersion должно быть "1". Пути входа указаны относительно каталога плагина. Вклады могут объявлять команды, панели, постпроцессоры, операции и вспомогательные инструменты; объявление вклада не привязывает эту функцию к каждому хосту.
Схема позволяет опционально signature и dev поля. Текущий рабочий хост записывает эти значения, но не выполняет проверку криптографической подписи во время установки. Поле подписи само по себе не является свидетельством проверенного издателя.
Вход в модуль и функции AI
definePlugin — это типизированный помощник по идентификации для модуля с манифестом и activate(ctx). Активация может вернуть функцию очистки, а модуль может раскрыть deactivate. SDK описывает эти перехватчики жизненного цикла; их доступность зависит от начальной загрузки конкретного рабочего, как подробно описано ниже.
Функции помощника экспортируются через aiTools записывать; вклад entry называет функцию в этой записи. Вклад инструмента включает его описание, схему параметров JSON и read или write добрый. Инструмент записи направляется через запрос на одобрение человеком во встроенном помощнике; внешний мост получает только разрешенные для чтения инструменты плагина.
Объедините запись работника как автономный модуль. Рабочий хост считывает источник записи и импортирует его через модуль больших двоичных объектов. Рассматривайте относительный импорт пакетов или файлов как отдельную проблему интеграции, а не предполагайте загрузчик файловой системы в стиле Node.
API с контролем возможностей
SDK распознает drawing:read, drawing:write, toolpath:read, storage, ui:panel, и ai:tool. Рисование записи подразумевает чтение рисунка. Общий хост извлекает эффективные возможности из установленного манифеста и проверяет их на RPC; приложение для внедрения решает, какие манифесты и поверхности оно желает загрузить.
Контекст SDK может предоставлять доступ к операциям чтения чертежей и исправлениям Add/Update/RemoveEntity, чтению траектории инструмента/программы, хранению секретных строковых значений ключа и декларативной регистрации команд/панелей. Отсутствующие услуги отсутствуют в контексте. Использование ключей хранения plugin:<id>: пространства имен и отклонять абсолютные ключи или ключи родительского обхода.
Загрузчик Production Assistant поддерживает только ai:tool. Манифест, запрашивающий возможности рисования, траектории, хранилища или пользовательского интерфейса, пропускается с предупреждением. Он не предоставляет эти поверхности молча и не загружает их более широкие возможности в хост-помощник.
Загрузка и жизненный цикл работника
Чтобы включить расширение помощника, поместите его plugin.json и объединенная запись под <dataDir>/plugins/<id>/ и перечислите идентификатор в <dataDir>/plugins/enabled.json, массив JSON. Идентификатор папки должен соответствовать манифесту. Загрузка происходит во время сборки службы плагина помощника; сбойный плагин регистрирует предупреждение без остановки приложения.
Общий хост поддерживает состояния «установлено», «включено», «отключено» и «неисправно», включая установку, включение, отключение, удаление, вызов команды, вызов инструмента AI и операции настройки. Enable создает работника и завершает его загрузочное рукопожатие; отключить срывает его. При удалении удаляется состояние реестра и пространство имен хранилища посредством внедренных зависимостей хоста.
Рабочие процессы начинаются с пустой среды, а загрузочный модуль удаляет выбранные глобальные API. Это ограничение на уровне приложения, а не изолированной программной среды операционной системы: глобальные элементы Bun остаются доступными. Включите только код расширения, который подходит для запуска внутри границы процесса приложения.
Ограничения времени выполнения
Хост определяет настройку рабочей памяти в размере 256 МБ, ограничение скорости 2,000-вызовов в минуту и не более 64 ожидающих вызовов для каждого плагина. Поведение тайм-аута команды предоставляется узлом внедрения; помощник загрузчика использует 10 секунд. Вызовы инструментов искусственного интеллекта имеют отдельный крайний срок в 30 секунды. Тайм-ауты, отсутствие инструментов, сбои рабочих процессов, сбои возможностей и исчерпание очереди возвращают типизированные сбои хоста или читаемые результаты инструментов.
Отслеживание сбоев выявляет сбой плагина после трех сбоев в течение десяти минут. Эти элементы управления хостом связывают совместный RPC и поведение жизненного цикла; настройка памяти, передаваемая Bun, не заменяет отдельно изолированный исполняемый файл.
Пределы определены в apps/sidecar/src/plugins/host.ts: CALL_TIMEOUT_MS (5,000 мс за обычный вызов), AI_TOOL_TIMEOUT_MS (30,000 мс на вызов помощника), MEMORY_LIMIT_MB (256), CALL_RATE_LIMIT (2,000 вызовов на плагин в минуту), MAX_PENDING_CALLS (64) и CRASH_LIMIT (3 выходит из строя в течение 10-минуты CRASH_WINDOW_MS, после чего плагин автоматически отключается).
Установка ZIP и API плагина браузера
POST /api/plugins/install принимает многочастный архив. Установщик читает manifest.json из корня ZIP или из одного каталога верхнего уровня, проверяет манифест плагина браузера и сохраняет его файлы в папке <dataDir>/storage/plugins/<id>/. Браузер манифестирует использование main, engines.cadcamи список разрешений браузера, а не SDK. entry, apiVersion, и возможности.
GET /api/plugins перечисляет эти установленные записи; Детализация, включение/отключение, удаление, обновление и настройка конечных точек выполняются в их реестре. /api/plugins/bootstrap.js?id=… обслуживает JavaScript; /api/plugins/serve?id=…&file=… обслуживает файлы плагинов. Это текстовые/бинарные операции с объявленными типами контента.
Обозреватель локального реестра считывает метаданные пакета в разделе <dataDir>/plugins-registry. Это локальный каталог манифестов. Установка архива, листинг реестра и загрузка расширения Work Assistant — это отдельные операции.
SDK-помощники
effectiveCapabilities, hasCapability, и missingCapabilities поддержка проверки возможностей. requireCapability вызывает ошибку возможности, когда запрошенная контекстная поверхность отсутствует. storageNamespace и storageKey создавать ключи в пространстве имен; parseManifest проверяет JSON; manifestKey форматирует пару идентификатор/версия.
Точки входа в реализацию
packages/plugin-sdk/src владеет общедоступным манифестом, возможностью, контекстом, плагином и API-интерфейсами тестового хоста. apps/sidecar/src/plugins/host.ts владеет жизненным циклом работника и RPC; services/ai-plugins.ts владеет загрузкой файла согласия и регистрацией помощника. Установка браузера реализована в http/plugins.ts и repos/plugin-registry-repo.ts.
Обзор расширения
Сохраняйте точность схем вклада, возвращайте небольшие структурированные результаты и честно декларируйте поведение чтения/записи. Тестируйте на реальном хосте внедрения: доступность SDK не обеспечивает производственный доступ к чертежам, хранилищу, пользовательскому интерфейсу или почтовым реестрам. автономный плагин nikcli является клиентом действий HTTP и имеет другое назначение, чем код, загруженный в рабочий процесс.
Заполните образец модуля помощника
The plugin.json пример выше имен aiTools.lookup. Это соответствующий самостоятельный index.js. Код модуля верхнего уровня запускается при импорте; объявленная функция поиска запускается при вызове.
export const aiTools = {
lookup: async () => ({
ok: true,
checklist: [
"Compare the drawing revision with the job traveller.",
"Record the measuring instrument and its calibration status.",
"Record each inspected dimension and the measured value."
]
})
} Это образцы инструкций для цехов, а не встроенный стандарт проверки. Замените их содержимым, которым фактически владеет ваше расширение. Чтобы допустить этот модуль при следующей инициализации службы, включенный файл:
["com.example.shop-helper"] Работающий каталог предоставляет идентификатор, полученный из идентификаторов плагинов и инструментов. Откройте для себя это через GET /api/ai/actions; не думайте, что ZIP-реестр браузера является включенным списком помощника. Перезагрузка приложения/службы – это надежный способ перечитать файл производственного согласия; этим загрузчиком не настроен наблюдатель файловой системы.
Источник: apps/sidecar/src/services/ai-plugins.ts, packages/ai/src/tools/plugin-tool.ts, и apps/sidecar/test/ai-plugin-tools.test.ts.
Схемы аргументов и ограничения жизненного цикла
Локальный идентификатор инструмента должен начинаться со строчной буквы и содержать строчные буквы, цифры или знаки подчеркивания, но не более 40 символов. Описания содержат символы 10–2,000. В вкладе должна быть указана непустая функция ввода и схема параметров JSON. Адаптер приложения проверяет аргументы перед вызовом работника; отказ может вернуть структурированный ok: false результат без закрытия плагина.
Публичный SDK описывает activate, уборка и deactivate точки входа. Обработчики активации/деактивации RPC текущего рабочего начальной загрузки Bun подтверждают сообщения жизненного цикла, но не вызывают эти экспортированные функции модуля. Поэтому расширения помощников должны помещать свое вызываемое поведение в aiTools и избегайте зависимости от обратных вызовов активации SDK для настройки или очистки.
Обычная рабочая загрузка также содержит обработчики рисования заполнителей, траекторий инструментов и пользовательского интерфейса. Они не представляют собой рабочие чертежи или интеграцию пользовательского интерфейса. Ограничение помощника погрузчика ai:tool предотвращает объявление этих неподдерживаемых поверхностей как доступ к рабочему приложению.
Источник: packages/plugin-sdk/src/manifest.ts, plugin.ts, apps/sidecar/src/plugins/host.ts (PLUGIN_BOOTSTRAP), и services/ai-plugins.ts.
Диагностика отсутствующего или неисправного расширения
- В каталоге нет инструментов: проверьте действительный включенный JSON, точное совпадение идентификатора папки и манифеста, декодирование манифеста и
ai:toolвозможности. Прочтите предупреждение при запуске пропущенного плагина. - Манифест запрашивает неподдерживаемые поверхности: удаляйте неподдерживаемые возможности только в том случае, если они действительно не нужны коду. Плагин-помощник не может получить доступ к рисованию и записи, просто объявив его.
- Нет такого инструмента: делать
contributes.aiTools[].entryсопоставить экспортированную функцию вaiTools. Идентификатор вклада и имя записи служат разным целям. - Ошибка проверки аргумента: проверьте схему JSON и обязательные поля. Неправильные значения отклоняются перед выполнением, как показывают тесты интеграции реальных рабочих процессов и приложений.
- Тайм-аут или неисправное состояние: расследовать блокировку работы, неразрешенные обещания или сбои; повторяющиеся сбои в работе плагина. Повторно включите только после устранения причины.
- Установщик ZIP отклоняет манифест: используйте плагин для браузера
manifest.jsonконтракт для этой конечной точки. Переименование работникаplugin.jsonне переводит свои поля.
Источник: apps/sidecar/test/plugins-ai-tools.test.ts, ai-plugin-tools.test.ts, plugins-http.test.ts, и src/plugins/host.ts.
Ссылка на манифест
Каждый плагин поставляется plugin.json. parseManifest(json) анализирует и проверяет его за один шаг, превращая синтаксическую ошибку JSON в тот же канал ошибок, что и ошибка схемы, поэтому экран установки должен обрабатывать только один тип ошибки.
| Поле | Правило |
|---|---|
id | Идентификатор обратного DNS: символы 3–128, строчные буквы, цифры и дефисы, например, как минимум в двух метках, разделенных точками. com.example.gear-generator. |
name | Непустое отображаемое имя. |
version | major.minor.patch, за которым может следовать суффикс предварительной версии, например -beta.1. |
apiVersion | Должно быть строка "1"; это единственная версия API плагина. |
entry | Путь к модулю ES относительно папки плагина. |
capabilities | Массив строк возможностей (см. ниже). Все, что находится за пределами закрытого списка, является явной ошибкой. |
contributes | Необязательный commands, panels, postProcessors, operations, и aiTools. |
signature | Подпись Ed25519 над хэшем архива; требуется для пакетной установки. |
dev | true отмечает плагин локальной разработки: проверки подписи пропускаются, а в пользовательском интерфейсе отображается значок. |
| Вклад | Поля |
|---|---|
commands[] | id, title, необязательный keybinding такой как Mod+Shift+G. |
panels[] | id, title, entry: экспортированная функция, возвращающая декларативное дерево панели. Никогда не бывает доступа к DOM. |
postProcessors[] | id, title, entry: экспортированный (program, options) => string функция. |
operations[] | id, title, entry: экспортированная запись с параметром schema и чистый generate(params, geometry, tool, stock) который возвращает траекторию инструмента. |
aiTools[] | id соответствие ^[a-z][a-z0-9_]{0,39}$, description (символы 10–2,000; модель читает их), kind read или write, parameters (JSON-схема аргументов) и entry. |
Помощники: manifestKey(m) возвращает id@version; requestedCapabilities(m) возвращает отсортированный список возможностей для отображения; isDevPlugin(m) и isSigned(m) ответьте на вопросы по политике установки.
Возможности и контекст плагина
Возможности — это единственное, через что может действовать плагин. Манифест объявляет, что нужно плагину, пользователь предоставляет подмножество, а хост создает контекст, который содержит именно предоставленные поверхности. Каждая поверхность является необязательной в этом типе, поэтому недостающая возможность видна как во время компиляции, так и во время выполнения, а не становится молчаливой неактивной.
| Возможность | Контекстная поверхность | Позволяет | подразумевает |
|---|---|---|---|
drawing:read | ctx.drawing.read() | Прочтите открытый чертеж (или undefined когда ни один не открыт). | — |
drawing:write | ctx.drawing.patch(patch) | Применять AddEntity, UpdateEntity, или RemoveEntity патчи; возвращает новую ревизию. | drawing:read |
toolpath:read | ctx.toolpath.list(), .program(id) | Чтение траекторий и программ G-кода. | — |
storage | ctx.storage | Строки значений ключа в пространстве имен: get, set, delete, keys. | — |
ui:panel | ctx.ui | registerCommand и registerPanel (только декларативный). | — |
ai:tool | нет (явный вклад) | Предлагайте инструменты помощнику и автономному nikcli только для чтения. | — |
effectiveCapabilities(granted) устраняет последствия, поэтому плагин, который объявляет drawing:write не нужно декларировать drawing:read. Каждый контекст также имеет pluginId, решено capabilitiesи log с debug, info, warn, и error; хост добавляет к строкам журнала идентификатор плагина. Использовать requireCapability(ctx, capability, surface) получить поверхность или потерпеть неудачу с CapabilityError это имя недостающего гранта.
Протестируйте плагин с помощью тестового хоста SDK.
createTestHost создает хост в памяти с теми же правилами возможностей, что и сайдкар. В контексте отображаются только предоставленные возможности, и вы можете предоставить чертеж, траектории и программы. Пример ниже завершен и работает с bun в рабочем пространстве.
import { cad } from "@cadcamfun/core"
import { createTestHost, definePlugin, requireCapability, testManifest } from "@cadcamfun/plugin-sdk"
const manifest = testManifest({
id: "com.example.frame",
capabilities: ["drawing:write", "storage", "ui:panel"],
})
const plugin = definePlugin({
manifest,
activate(ctx) {
const drawing = requireCapability(ctx, "drawing:write", "drawing")
ctx.ui?.registerCommand({ id: "frame.add", title: "Add frame line" })
ctx.storage?.set("runs", "1")
drawing.patch({
_tag: "AddEntity",
entity: { ...cad.baseEntity("frame-1"), _tag: "Line",
start: { x: 0, y: 0 }, end: { x: 100, y: 0 } },
}) // returns revision 1
return () => ctx.log.info("teardown") // runs on deactivation
},
})
const host = createTestHost({ manifest, drawing: cad.emptyDrawing("d1", "Demo") })
const stop = await host.activate(plugin)
host.drawing()?.entities.length // 1
host.context.storage?.get("runs") // "1"
host.ui.commands // [{ id: "frame.add", title: "Add frame line" }]
await stop()
// Without the grant, requireCapability throws:
const denied = createTestHost({ manifest, granted: ["storage"] })
await denied.activate(plugin)
// CapabilityError: Plugin com.example.frame may not use "drawing:write":
// it was not granted at install time testManifest(overrides)начинается с минимального допустимого манифеста (com.example.test-plugin, версия 1.0.0, API 1, записьindex.js, нет возможностей).grantedпо умолчанию соответствует всему, что запрашивает манифест. Передайте меньший список, чтобы проверить запрещенные пути.host.storageэто снимок, сделанный при создании хоста. Прочитайте живые значения черезhost.context.storage.host.on(commandId, handler)иhost.invoke(commandId, args)выполнять зарегистрированные команды.runPostProcessorзапускает добавленную публикацию для программы иkeyOf(pluginId, key)показывает ключ хранения в пространстве имен, чтобы тесты могли подтвердить изоляцию.
Как приложение загружает плагины-помощники
- При запуске сайдкар читает
<data dir>/plugins/enabled.json, массив идентификаторов плагинов в формате JSON. Ничего не загружается, если это не указано там. - Для каждого идентификатора он читает
<data dir>/plugins/<id>/plugin.jsonи анализирует его. Имя папки должно совпадать с манифестом.id. - Только
ai:toolподключен к этому хосту. Манифест, который запрашивает рисование, траекторию инструмента, хранилище или доступ к пользовательскому интерфейсу, пропускается с предупреждением, а не загружается поверхностями, которые молча ничего не делают. - Плагин установлен на рабочий хост и включен. Плагин, который не загружает логи
Plugin <id> was not loaded: ...и никогда не останавливает запуск приложения. - Каждый внесенный инструмент предлагается помощнику как
plugin_<slug of plugin id>_<tool id>, не более 80 символов, где фрагмент преобразует идентификатор в нижний регистр и заменяет другие символы символами подчеркивания.com.example.bolt-circleс инструментомbolt_circleстановитсяplugin_com_example_bolt_circle_bolt_circle. - Аргументы проверяются на соответствие схеме JSON инструмента до того, как их увидит рабочий процесс. Если длина схемы превышает 20,000 символов, не является схемой объекта или не может быть преобразована, хост принимает любой объект, и плагин должен его проверить.
- Вызов, который выдает ошибку, истекает время ожидания или обнаруживает, что плагин исчез, возвращается.
{ ok: false, error }(текст ошибки длиной до 500 символов) помощнику вместо сбоя поворота. Аwriteинструмент подтверждается человеком перед каждым звонком, что бы ни говорили его аргументы.
Не песочница операционной системы
У рабочего процесса нет собственного дескриптора процесса, выборки или файла, но глобальные элементы Bun остаются доступными внутри него. Включайте только те плагины, коду которых вы доверяете, и сведите инструменты записи к минимуму.
Правила идентификатора и версии, проверено
| Ценить | Действительный? | Правило |
|---|---|---|
com.example.gear-generator | да | Обратный DNS: строчные буквы, цифры и -не менее двух символов: 3–128 |
a.b | да | Двух однобуквенных сегментов достаточно |
gear | нет | Нужна хотя бы одна точка |
Com.Example.x | нет | Заглавные буквы не допускаются |
com.example_x.y | нет | Подчеркивание не допускается |
| Версия | Действительный? |
|---|---|
1.0.0 | да |
1.2.3-beta.1 | да |
1.0 | нет: необходимо три цифры |
v1.0.0 | нет: без префикса |
apiVersion должна быть строка "1", единственный существующий основной API-интерфейс плагина. Идентификаторы инструментов ИИ должны совпадать ^[a-z][a-z0-9_]{0,39}$ и отображаются ассистенту как plugin_<plugin>_<id>; описания должны состоять из символов 10–2,000, поскольку модель их читает.
Типы вкладов
| Ключ | Поля | Цель |
|---|---|---|
commands | id, title, необязательный keybinding (e.g. Mod+Shift+G) | Команды в палитре |
panels | id, title, entry | Панель, отображаемая из декларативного дерева, которую возвращает именованная функция; нет доступа к DOM |
postProcessors | id, title, entry | A (program, options) => string сообщение зарегистрировано во время выполнения |
operations | id, title, entry | Экспортированный { schema, generate } записывать |
aiTools | id, description, kind читать|писать, parameters (схема JSON), entry | Инструменты, предлагаемые помощнику; инструмент записи подтверждается перед каждым звонком |
Другие поля манифеста: signature (Редактируйте25519 поверх хэша архива, необходимо для пакетной установки) и dev (плагин локальной разработки: пропускает проверку подписи и показывает значок).
Разрешение возможностей, протестировано
import { effectiveCapabilities, missingCapabilities, storageKey, requireCapability } from "@cadcamfun/plugin-sdk"
effectiveCapabilities(["drawing:write", "storage"])
// ["drawing:read", "drawing:write", "storage"] (write implies read; sorted)
missingCapabilities(["drawing:read", "toolpath:read", "ai:tool"], ["drawing:write"])
// ["toolpath:read", "ai:tool"]
storageKey("com.example.gear", "presets/m2") // "plugin:com.example.gear:presets/m2"
storageKey("com.example.gear", "../x")
// RangeError: storage key "../x" may not escape the plugin namespace (same for "/abs")
requireCapability(ctxWithoutDrawing, "drawing:read", "drawing")
// CapabilityError (_tag "CapabilityDenied"):
// Plugin com.example.gear may not use "drawing:read": it was not granted at install time | Поверхность контекста | Присутствует при предоставлении | Методы |
|---|---|---|
drawing | drawing:read или drawing:write | read() → рисунок или undefined; patch(p) → новая редакция, с AddEntity, UpdateEntity, RemoveEntity патчи |
toolpath | toolpath:read | list(), program(toolpathId) |
storage | storage | get, set, delete, keys; строковые значения |
ui | ui:panel | registerCommand, registerPanel |
log | всегда | debug, info, warn, error |