Сайт

Обзор

Код расширения выполняется в extension host с глобальным объектом sdk, поэтому импортировать его не нужно. Всё, что расширение делает во время выполнения — команды, уведомления, граф, процессы — проходит через него.

import type { ExtensionContext } from '@fragmenta/extension'

export function activate(context: ExtensionContext) {
  context.subscriptions.push(
    sdk.commands.registerCommand('sayHello', () => {
      sdk.window.showInfoMessage('Привет из моего расширения')
    }),
  )
}

Типы

Определения типов включены в пакет @fragmenta/extension. Добавьте его в devDependencies для того, чтобы получить типы для глобального sdk:

{
  "devDependencies": {
    "@fragmenta/extension": "latest"
  }
}

Помимо типов, пакет экспортирует несколько рантайм-значений:

| Экспорт | Вид | Описание | | --- | --- | --- | | NodeKind, PortType, PortDirection, NotificationType, ProblemSeverity | enum'ы | Значения, используемые нодовым редактором, уведомлениями и проблемами.| | ProjectPanelIds | константа | Идентификаторы панелей рабочей области проекта. | | PROJECT_EXTENSION_ID | константа | Идентификатор встроенного расширения проекта. | | SDK_EXEC_PERMISSION | константа | Имя разрешения 'exec'. |

AssetKind экспортируется только как тип. Во время выполнения сравнивайте значение asset.kind напрямую с 'node' или 'edge'. Всё остальное предоставляется глобальным sdk.

Некоторые типы, перечисленные на этих страницах, например SdkAuthSession или SdkDockerContainerInfo нельзя импортировать напрямую, используя имя. Они показаны здесь для справки. При необходимости их можно извлечь из экспортируемого ExtensionSdk следующим образом:

import type { ExtensionSdk } from '@fragmenta/extension'

type SdkAuthSession = NonNullable<Awaited<ReturnType<ExtensionSdk['auth']['getSession']>>>

Соглашения

  • Асинхронность — большинство методов возвращают Promise, поскольку SDK взаимодействует с приложением по RPC.

  • События — для полей типа Event<T> можно подписаться, передав обработчик. Подписка взовращает объект IDisposable, который можно потом почистить:

    const sub = sdk.project.nodeEditor.onNodeAdded((nodeId) => { /* ... */ })
    
  • Disposable-объекты — всё, что вы регистрируете или создаёте (команды, вебвью, элементы строки состояния, подписки на события), возвращает IDisposable. Добавьте его в context.subscriptions, чтобы оно освобождалось при деактивации

  • Ошибки — неудачный вызов отклоняется с Error, в message которого описана причина.

Разрешения

Только два API закрыты разрешениями, задекларированными в манифесте:

| Permission | Что закрывает | | --- | --- | | exec | Весь sdk.exec: execute, start, kill и kill() у дескриптора. | | fs:extensions | Весь sdk.fs.extensions. |

{ "contributes": { "permissions": ["exec", "fs:extensions"] } }
  1. Не объявлено — каждый вызов немедленно завершается ошибкой, и пользователю не показывается запрос..
  2. Объявлено — первый вызов показывает запрос Allow / Deny. Любые последующие вызовы, сделанные пока запрос открыт, будут ждать того же ответа пользователя.
  3. Запомнено — выбор пользователя (включая Deny) сохраняется, поэтому его больше не спросят, пока расширение не будет удалено. Если пользователь выбрал Deny, все будущие вызовы будут немедленно завершаться ошибкой.

Всё остальное — включая sdk.fs.readFile, sdk.fs.extension и sdk.docker — не требует разрешений.

Активация и деактивация

Модуль расширения экспортирует activate и, опционально, deactivate. Обе функции могут быть async, поскольку хост ожидает возвращённый Promise:

import type { ExtensionContext } from '@fragmenta/extension'

export async function activate(context: ExtensionContext) {
  // регистрируем команды, создаём webviews, запускаем работу
}

export async function deactivate() {
  // останавливаем процессы, сохраняем состояние
}

Если activate выбрасывает ошибку или отклоняется, процесс активации завершается неудачно. При деактивации расширения хост выполняет следующие шаги:

  1. Дожидается deactivate(), если она экспортирована.
  2. Освобождает то, что расширение зарегистрировало через объект sdk — включая команды, оркестраторы, ИИ-инструменты, веб-представления, элементы строки состояния, каналы вывода, сообщённые проблемы и файловые дескрипторы.
  3. Очищает context.subscriptions по порядку, вызывая dispose() для каждого элемента. Если в одном dispose() возникает ошибка, она логируется и не мешает очистке остальных элементов.

Подписки на события автоматически не освобождаются. Необходимо вручную добавлять их в context.subscriptions. Аналогично, процессы, запущенные через sdk.exec, продолжают работать, если вы их явно не завершите в deactivate.

ExtensionContext

activate получает ExtensionContext:

| Член | Тип | Описание | | --- | --- | --- | | subscriptions | IDisposable[] | Освобождаются при деактивации расширения. | | extension | ExtensionDescription | Описание расширения (ниже). | | extensionUri | URI | Папка установки расширения в виде URI. | | extensionPath | string | Та же папка в виде нативного пути файловой системы. | | asAbsolutePath(relativePath) | string | Нативный путь к файлу внутри папки расширения. | | platform | ExtensionPlatform | 'win32' \| 'darwin' \| 'linux' \| 'web' \| 'unknown'. | | env | ExtensionEnvironment | Флаги окружения (ниже). |

asAbsolutePath принимает разделители / и \, игнорирует пустые сегменты и возвращает нативный путь. Он не проверяет, что результат остаётся внутри папки расширения.

Значение платформы определяется по строке платформы и user agent браузера. Это означает, что оно определяет базовую операционную систему, даже когда приложение работает как веб-приложение — например, браузер на macOS сообщает 'darwin'. Значение 'web' указывает на браузер, в котором ОС не удалось распознать, а 'unknown' — на настольное приложение, работающее на нераспознанной ОС. Чтобы определить, работает ли ваше расширение в настольном приложении или в веб-приложении, используйте env.isDesktop и env.isWeb.

ExtensionDescription
interface ExtensionDescription {
  readonly id: ExtensionId            // '<publisher>.<name>'
  readonly uuid: string
  readonly versionId: string          // id установленной версии
  readonly version: string
  readonly name: string
  readonly displayName: string
  readonly publisher: string
  readonly location: URI              // папка установки
  readonly type: 'system' | 'user' | 'dev'
  readonly manifest: {                // разобранный package.json
    name: string
    publisher: string
    version: string
    displayName: string
    engines: { sdk: string }
    description?: string
    main?: string
    icon?: string
    contributes?: Record<string, unknown>
    activationEvents?: string[]
    categories?: string[]
    extensionDependencies?: Record<string, string>
    git?: { repo?: string; provider?: 'github' | 'gitlab'; defaultBranch?: string; commit?: string }
    billing?: {
      model?: 'paid' | 'freemium'
      features?: { id: string; displayName?: string; description?: string; type?: 'subscription' | 'one-time' | 'metered' }[]
    }
  }
}
ExtensionEnvironment
interface ExtensionEnvironment {
  readonly platform: 'win32' | 'darwin' | 'linux' | 'web' | 'unknown' // то же, что context.platform
  readonly isDesktop: boolean   // запущено в десктопном приложении
  readonly isWeb: boolean       // запущено в веб-приложении
  readonly isWindows: boolean   // platform === 'win32'
  readonly isMac: boolean       // platform === 'darwin'
  readonly isLinux: boolean     // platform === 'linux'
  readonly userAgent: string
  readonly channel: 'release' | 'dev' | 'preview' // канал релизов приложения
}

Неймспейсы

| Неймспейс | Страница | Для чего | | --- | --- | --- | | sdk.commands | Commands | Регистрация обработчиков, выполнение команд. | | sdk.window | Window | Уведомления, quick input и диалоги подтверждения, модалки, файловые диалоги, statusbar, output-каналы. | | sdk.window (webviews) | Webviews | Создание webview и обмен сообщениями с ними. | | sdk.workspace | Workspace | В каком workspace пользователь и что там открыто. | | sdk.workspace (настройки) | Configuration | Чтение и изменение настроек. | | sdk.project | Project | Активный проект, его события, панели. | | sdk.project.nodeEditor | Node Editor | Чтение и изменение графа: nodes, edges, порты, состояние выполнения. | | sdk.expressions | Expressions | Подсказки и диагностика для полей {{…}}, списки вариантов для параметров. | | sdk.orchestrator | Orchestrators | Регистрация orchestrator'а, который запускает граф. | | sdk.problems | Problems | Регистрация проблем с решениями в один клик. | | sdk.fs | File System | Чтение файлов, хранилище расширения. | | sdk.exec | Exec | Запуск системных процессов. | | sdk.docker | Docker | Запуск и инспекция контейнеров. | | sdk.ai | AI Tools | Реализация tools для AI-ассистента. | | sdk.auth · sdk.i18n · sdk.team · sdk.extensions · sdk.assets · sdk.input | Platform APIs | Сессия, локализация, team, реестр расширений, assets, клавиатура. |

Форматы файлов определений (schema.json для nodes и edges, темы) описаны в Workshop: nodes, edges и themes.