Десктопные браузеры
Неймспейс десктопных браузеров даёт плагину настоящее окно браузера на хосте для автоматизации, которой нужен авторизованный профиль.
// plugins/browser-automation/server.ts (abridged) — the full cycleconst desktop = bb.sdk.experimental_desktopBrowsers;const { instances } = await desktop.listInstances({ hostId: selection.hostId });const instance = instances.find((c) => c.instanceId === selection.instanceId);const scope = { hostId: selection.hostId, instanceId: instance.instanceId, generation: instance.generation, threadId: input.threadId };const result = await desktop.createTab({ ...scope, url: "about:blank", presentation: "hidden" });const lease = await desktop.acquireControl({ ...scope, tabIds: [result.tab.tabId], controllerLabel: "Browser Automation", ttlMs, allowPersonal: selection.tabId !== undefined });const connection = await desktop.openConnection({ ...scope, leaseId: lease.leaseId });if (connection.hostId !== scope.hostId) throw new Error("Desktop connection returned a different host");session.expiresAt = Math.min(session.expiresAt, lease.expiresAt, connection.expiresAt);12 элементов неймспейса, проверено на закреплённом релизе: listInstances · listTabs · createTab · acquireControl · openConnection · releaseControl · revealTab · closeTab · captureTab · listImportSources · importCookies · subscribe; subscribe — это «a disposable two-second polling subscription».
Особенность. Этой поверхности вообще нет в файле backend-contract.ts: она доступна только через bb.sdk, и у неё нет типа контракта плагина.
Дисциплина. Значение ttlMs реальное (30 минут в browser-automation), а время жизни сессии должно быть min из её собственного TTL, аренды и соединения. allowPersonal: true — только когда пользователь явно выбрал существующую вкладку; плагин помнит, чем владел (owned), поэтому знает, что может закрыть. Несовпадение hostId соединения и скоупа — фатальная ошибка.
Кто поставляет. Единственный потребитель — browser-automation.