Skip to content

От нуля до вашего модуля в вашей песочнице ​

От пустой папки до вашего модуля внутри Building OS, в вашей собственной песочнице (или в общей с коллегой, см. Два разработчика, одна песочница). Вашего времени уйдёт около 30 минут, плюс одно ожидание нашего ответа после шага 3, пока мы заводим вам учётную запись в песочнице; шаги 4 и 5 тем временем можно выполнять. Шаги идут по порядку, потому что каждому нужен предыдущий, и каждый ссылается на страницу, где он разобран подробно.

Перед началом ​

Вам нужны четыре вещи. Если чего-то не хватает, напишите контакту, указанному в приветственном сообщении, на почту или в Telegram; адрес developers@tango.vision доходит до тех же людей. Отвечаем в тот же рабочий день по московскому времени.

  • Учётная запись разработчика в реалме developers. Регистрация только по приглашениям: учётную запись создаём мы, а пароль задаёте вы. С ней вы выпускаете API-ключи на портале. См. Учётная запись разработчика.
  • Токен реестра для npm.k8s.tangovision.dev. SDK лежит в закрытом реестре, токен выдаётся лично вам. Он приходит отдельным сообщением от вашего контакта, а не в письме об учётной записи. Никогда не коммитьте его.
  • Учётная запись в песочнице — мы заводим её, когда песочница создана (шаг 3). Приглашённые разработчики получают имя пользователя и временный пароль, отдельные от учётной записи разработчика. Сотрудники Tango Vision входят под корпоративной учётной записью — после того как их включили в группу /sandbox-developers, а оператор связал с ней их учётную запись в песочнице; пароля у них нет. См. Войдите.
  • Node 24 (подойдёт и 22) и pnpm 10.18.2 — ровно та версия pnpm, которую использует CI платформы. Для последнего шага — Chrome или Firefox: Safari не может загрузить модуль с вашей машины.

CLI, сообщения об ошибках, README каркаса и история изменений SDK — на английском. Ищите текст ошибки дословно в таблице Если что-то не так. В src/locales/ru.json каркаса стоит заглушка «TODO: translate» — так и задумано, замените её своим текстом.

Однократная настройка ​

Corepack входит в Node 24 и ставит именно эту версию pnpm:

bash
corepack enable && corepack prepare pnpm@10.18.2 --activate
pnpm -v    # ожидается 10.18.2

Если pnpm -v показывает другую версию, значит, pnpm, установленный другим способом (через npm или Homebrew), стоит в PATH раньше; удалите его или переставьте corepack вперёд.

Затем направьте область @tv на закрытый реестр так, чтобы токен читался из переменной окружения и в самом файле секрета не было:

bash
# ~/.npmrc
@tv:registry=https://npm.k8s.tangovision.dev/
//npm.k8s.tangovision.dev/:_authToken=${TV_NPM_TOKEN}
bash
export TV_NPM_TOKEN=...              # токен реестра; храните в профиле оболочки или в менеджере секретов
npm view @tv/extension-sdk version   # ожидается 1.15.1 или новее

Используйте @tv/extension-sdk 1.15.1 или новее; вывод ниже получен в 1.15.1. В более старых версиях есть ошибки, которые ломают шаги этого руководства: от каркаса, который не собирается, до login, который падает в Windows. Если модуль уже создан одной из них, что поправить вручную, перечислено в разделе Известные проблемы по версиям SDK. Подробности, включая передачу токена в сборку Docker как секрета: Начало работы.

1. Создайте каркас модуля ​

bash
npx @tv/extension-sdk init-module hello --category=operations --external --scope=acme --author="Acme Ltd"
cd tv-module-hello
pnpm install

В --scope укажите npm-область вашей компании, в --author — её название. Так модуль будет записан на вашу компанию: id и имя пакета становятся @acme/module-hello, а автор в манифесте — Acme Ltd. Без этих флагов модуль получит id @tv/module-hello и автора «Tango Vision», а @tv — наша область. Часть module-<slug> оставьте как есть: адрес модуля в оболочке — это часть id после module-.

--external генерирует CI, который работает на раннерах GitHub с вашим собственным секретом TV_NPM_TOKEN. Без него сгенерированный workflow вызывает actions из закрытого репозитория Tango Vision и вне нашей организации падает.

Вы получаете module-manifest.json (контракт: id, разрешения, события, куда монтируется UI), src/Shell.tsx (компонент, который рисует оболочка), vite.config.ts (remote федерации, экспортирующий ./Shell) и README с портами и URL, которые встретятся ниже.

bash
pnpm dev          # автономный просмотр с фиктивным контекстом платформы, http://localhost:5001
pnpm test
npx @tv/extension-sdk validate module-manifest.json
npx @tv/extension-sdk check-exposes module-manifest.json --config=./vite.config.ts

Правьте Shell.tsx и locales/, пока автономный просмотр не покажет то, что нужно. Внутри настоящей оболочки работают только определённые вызовы SDK: useSelectedBuildingId() из @tv/extension-sdk/react для выбранного здания и getAccessToken() или authorizationHeader() из @tv/extension-sdk/context для аутентификации ваших запросов к API — на каждый запрос. Никогда не читайте localStorage['access_token']. React-контекст не пересекает границу федерации, поэтому usePlatformContext() внутри оболочки бросает исключение.

Подробно: Ваш первый модуль и Вызов API из модуля.

2. Получите API-ключ песочницы ​

Откройте портал разработчика, войдите с учётной записью разработчика и выпустите ключ. Он показывается один раз. По умолчанию у ключа область действия sandbox, он истекает через 90 дней, отозвать его можно там же.

bash
export TV_API_TOKEN=tvk_...      # ключ с портала; или: npx @tv/extension-sdk login

Держите этот ключ в TV_API_TOKEN до конца руководства: по нему шаг 5 находит вашу песочницу.

В Windows login сохраняет сессию в файл в профиле пользователя (~/.config/tv-sdk/credentials.json) и сообщает об этом: сессия больше, чем вмещает диспетчер учётных данных Windows. SDK 1.15.0 и более ранние в этом месте падают (Известные проблемы). Ключ с портала работает везде.

Подробно: Получить API-ключ песочницы, API-ключи и Вход через CLI.

3. Создайте песочницу ​

bash
npx @tv/extension-sdk sandbox create \
  --name=hello-dev --type=office --storeys=2 --area-sqm=5000 --ttl-days=30

Создание занимает от одной до нескольких минут; команда опрашивает сервис, пока песочница не станет ready, и затем печатает:

✓ Sandbox ready:
  id:             sbx_…
  name:           hello-dev
  slug:           <slug>
  organizationId: <organization id>
  status:         ready
  api:            https://<slug>.sandbox.k8s.tangovision.dev
  console:        https://<slug>.sandbox.k8s.tangovision.dev
  expires:        2026-10-26T…

  Signing in to the sandbox shell needs sandbox logins, which Tango Vision sets up.
  Send this line to your Tango Vision contact (or developers@tango.vision):

    Please set up sandbox logins for slug=<slug> (organizationId=<organization id>)

  Meanwhile, register your module (serve it first: pnpm dev:remote + pnpm serve:remote):
    npx @tv/extension-sdk sandbox install module-manifest.json --sandbox=sbx_… --remote-entry=http://localhost:6001/assets/remoteEntry.js
СтрокаЧто это
idsbx_… — идентификатор песочницы, он нужен на шаге 5
slugSlug песочницы: начало её адреса; под него заводят ваши учётные записи в песочнице
organizationIdОрганизация песочницы; её несёт ваша учётная запись в песочнице
apiСобственный tv-api песочницы
consoleТот же хост: оболочка песочницы, которую вы откроете на шаге 6
expiresКогда песочница будет удалена вместе со всем содержимым
Please set up sandbox logins …Это вы пришлёте нам: см. ниже
npx … sandbox install …Команда шага 5 с вашим идентификатором, одной строкой, чтобы вставлялась в любую оболочку

sandbox connect в этом руководстве не нужен: шаг 5 находит всё по идентификатору. connect печатает собственный URL tv-api и токен администратора песочницы как настройки TV_API_URL=… / TV_API_TOKEN=… — только для серверного кода (скрипта, локального бэкенда). Никогда не помещайте этот токен в код для браузера и не экспортируйте эту пару в терминале, где запускаете команды sandbox: тогда sandbox list и create будут обращаться к вашей песочнице (см. Если что-то не так).

Внутри: наполненное офисное здание с этажами, помещениями и оборудованием, собственная база PostgreSQL и собственный tv-api. Данные синтетические — пусть такими и остаются: не загружайте в песочницу реальные данные компании, если это не согласовано с нами письменно. Типы: office, mall, university. Не больше 3 песочниц одновременно.

Срок жизни. 30 дней — максимальный срок при создании; без --ttl-days песочница живёт 14 дней. Пока она работает, её можно продлить дважды, по 7 дней:

bash
npx @tv/extension-sdk sandbox extend sbx_... --days=7

Напоминаний перед истечением нет, поэтому запишите дату из expires. Истёкшую песочницу продлить нельзя: её база и хост удаляются, а у новой песочницы будет новый slug, и отправку slug (ниже) придётся повторить.

Минуту-две после ready HTTPS-сертификат песочницы может быть ещё не выпущен. Тогда sandbox install падает с Cannot reach https://<slug>.sandbox.k8s.tangovision.dev/…: fetch failed, а браузер предупреждает, что подключение не защищено. Подождите минуту и повторите.

Теперь пришлите нам строку для входа

Отправьте строку Please set up sandbox logins for slug=… (organizationId=…), которую напечатал create, контакту, указанному в приветственном сообщении, на почту или в Telegram; адрес developers@tango.vision доходит до тех же людей. Отвечаем в тот же рабочий день по московскому времени. Мы разрешаем вход через хост песочницы и заводим (для сотрудников — связываем) вашу учётную запись в песочнице. Пока мы этого не сделали, оболочка не сможет вас впустить, но для шагов 4 и 5 входить не нужно — продолжайте. Каждый раз, когда вы создаёте новую песочницу, этот шаг повторяется.

Потеряли строку? npx @tv/extension-sdk sandbox list снова покажет slug и organizationId каждой песочницы. Пришлите нам только эти два значения: в выводе с --format=json есть ещё и apiToken каждой песочницы, а его никому передавать нельзя.

Подробно: Песочницы по запросу — что изолировано, а что общее, квоты и API, на котором работает эта команда.

4. Отдавайте remote со своей машины ​

Remote федерации существует только в сборке; pnpm dev не создаёт remoteEntry.js. Два терминала, запускайте в таком порядке:

bash
pnpm dev:remote     # vite build --watch
pnpm serve:remote   # vite preview --port 6001 --strictPort, CORS включён

Пока первая сборка не закончилась, serve:remote останавливается с The directory "dist" does not exist. Did you build your project?; запустите его снова, когда dev:remote соберёт проект.

Ваш remote доступен по адресу http://localhost:6001/assets/remoteEntry.js. Порт зафиксирован намеренно: если 6001 занят, команда останавливается с Port 6001 is already in use, а не переезжает молча на другой порт, из-за чего реестр указывал бы в пустоту. Пишите localhost, а не 127.0.0.1: в macOS сервер preview отвечает только на localhost.

Подробно: Отдавайте remote со своей машины.

5. Установите модуль в свою песочницу ​

Запустите команду, которую напечатал create, в терминале, где в TV_API_TOKEN по-прежнему ключ с портала из шага 2 (или где вы выполнили login):

bash
npx @tv/extension-sdk sandbox install module-manifest.json --sandbox=sbx_... --remote-entry=http://localhost:6001/assets/remoteEntry.js

По --sandbox команда находит песочницу в сервисе, который управляет песочницами, с вашим ключом с портала, а для самой установки берёт собственный токен песочницы. Вам этот токен не нужен. Команда записана одной строкой намеренно: перенос через \ работает в bash, но в PowerShell или cmd превращается в две команды.

sbx_… — идентификатор вашей песочницы из шага 3, а не slug из её URL. Потеряли его? npx @tv/extension-sdk sandbox list показывает идентификаторы всех ваших песочниц; портал показывает песочницы только по имени.

Команда регистрирует манифест в реестре вашей песочницы с remote entry на localhost и выдаёт модулю лицензию на наполненное здание. Она печатает URL, который нужно открыть. Запускайте её заново при каждом изменении манифеста; изменения кода переустановки не требуют — оболочка каждый раз загружает ваш remote заново.

Передавайте remote entry ровно так, как выше. Не 127.0.0.1 (см. шаг 4) и не порт pnpm dev 5001: dev-сервер отвечает на этот путь HTML-страницей, и оболочка показывает Module failed to load, а консоль браузера сообщает о скрипте-модуле с MIME-типом "text/html".

Если команда падает, в сообщении названы шаг и сервис, который отказал: поиск в сервисе, управляющем песочницами, либо регистрация манифеста, чтение зданий или выдача лицензии в tv-api вашей песочницы. Как это исправить — в таблице Если что-то не так.

Подробно: Установите модуль в свою песочницу.

6. Откройте его в оболочке песочницы ​

https://<slug>.sandbox.k8s.tangovision.dev/sandbox/hello
  1. Используйте Chrome или Firefox. Приглашённые разработчики входят под учётной записью в песочнице, данные которой мы прислали; при первом входе нужно задать новый пароль. Сотрудники нажимают Tango Vision staff и входят под корпоративной учётной записью.
  2. Вы попадаете в Building OS как Administrator, с выбранным наполненным зданием.
  3. Откройте /sandbox/hello. Chrome может один раз спросить разрешение на доступ к локальной сети — разрешите. Ваш Shell.tsx отрисуется внутри оболочки.

Правьте, сохраняйте, перезагружайте. dev:remote пересобирает, и оболочка подхватывает новый бандл при следующей загрузке.

Подробно: Откройте и Войдите.

Два разработчика, одна песочница ​

Песочница принадлежит организации той учётной записи разработчика, которая её создала, а каждая учётная запись разработчика — отдельная организация. Поэтому, если над одной песочницей работают двое, тот, кто её не создавал, не достанет до неё своим ключом: sandbox list ничего не показывает, а sandbox install --sandbox=… отвечает 404. Как работать с общей песочницей:

  1. Разработчик A создаёт песочницу (шаг 3) и, как обычно, присылает нам её slug, указав, кто ещё над ней работает. Мы заводим каждому из вас учётную запись в песочнице.

  2. Мы присылаем разработчику B API-ключ, который действует от имени организации разработчика A. Срок его действия мы сообщим. B использует его вместо ключа с портала:

    bash
    export TV_API_TOKEN=tvk_...             # ключ, который мы прислали разработчику B
    npx @tv/extension-sdk sandbox list      # теперь показывает общую песочницу

    Ключи, которые B выпускает на портале сам, по-прежнему относятся к его собственной организации и общую песочницу не видят, а на странице портала у B песочниц не будет.

  3. Каждый из вас отдаёт модуль со своей машины по шагам 4 и 6, на http://localhost:6001. Запись в реестре указывает на localhost, а каждый браузер понимает под ним свою машину, так что каждый видит свою сборку.

  4. В песочнице одна запись реестра на модуль. Кто последним запустил sandbox install, тот перезаписал её для обоих. Поэтому переустанавливайте модуль только при изменении манифеста, всегда с --remote-entry=http://localhost:6001/assets/remoteEntry.js, и договоритесь, какая версия манифеста актуальна.

  5. Оба ключа позволяют продлевать, сбрасывать и удалять общую песочницу, а песочница, созданная любым из них, учитывается в одном и том же лимите в 3 песочницы. Договоритесь, кто из вас этим занимается.

Когда вы замените песочницу новой, пришлите нам её slug, и мы перенастроим на неё учётные записи обоих.

Правила, которые объясняют пустые страницы ​

  1. Модуль с localhost загружает только оболочка песочницы. Продуктивная оболочка не загрузит его никогда; к клиентам ваш модуль попадает только после того, как мы проверим исходный код и соберём его в нашем CI.
  2. Только loopback: localhost или 127.0.0.1. Адрес в локальной сети или туннель будут отклонены. Регистрируйте localhost: в macOS serve:remote не отвечает на 127.0.0.1.
  3. Модуль отрисовывается только в вашем браузере. Коллега, открывший тот же URL, получит ошибку загрузки: localhost — это его машина (если только он не отдаёт модуль сам, см. Два разработчика, одна песочница).
  4. Ваш бэкенд работает на вашей машине, и браузер может к нему обращаться, а платформа — нет: у песочницы нет выхода в интернет, поэтому Copilot не достанет до MCP-эндпоинта на localhost, а Copilot песочницы не может вызвать внешнюю LLM.
  5. Делите i18next и react-i18next в vite.config.ts либо оба, либо ни одного, и сохраните alias use-sync-external-store/shim, который записал каркас. Нарушение любого из правил ломается только внутри оболочки, где ваш CI этого не видит.

Полный список: Правила загрузки модуля с localhost.

Если что-то не так ​

Что вы видитеПричинаЧто делать
"useQuery" is not exported при сборкеКаркас SDK 1.14.0Создайте каркас заново версией 1.15.1 или новее либо выполните pnpm add -w @tanstack/react-query@^5
Missing required argument: <id> или 404 от sandbox connectНет идентификатора песочницы или он не тотnpx @tv/extension-sdk sandbox list показывает ваши идентификаторы (sbx_…)
sandbox list или create падают после того, как вы экспортировали пару TV_API_URL / TV_API_TOKEN из вывода sandbox connectЭта пара направляет CLI в tv-api вашей песочницы, а не в сервис, который управляет песочницами (install --sandbox с 1.15.1 её не учитывает)unset TV_API_URL TV_API_TOKEN (или откройте новый терминал), затем снова экспортируйте ключ с портала в TV_API_TOKEN
⚠ TV_API_TOKEN holds a sandbox's own token (tvs_sbx_…, …) или ⚠ TV_API_TOKEN is not a developer key from the portal (tvk_…) от installВ TV_API_TOKEN не ключ с портала, поэтому поиск песочницы его пропустил и взял сессию loginСнова экспортируйте ключ с портала в TV_API_TOKEN или выполните npx @tv/extension-sdk login
login падает: longer than the platform limit of 2560 charsДиспетчер учётных данных Windows не вмещает сессию, а SDK 1.15.0 и более ранние не переключаются на файлИспользуйте SDK 1.15.1 или новее — он сохраняет сессию в файл — либо ключ с портала в TV_API_TOKEN
The provisioner at … rejected your developer key (TV_API_TOKEN) (401) while looking up sandbox sbx_…Ключ с портала неверный, отозван или истёкВыпустите новый ключ на портале и положите его в TV_API_TOKEN или выполните npx @tv/extension-sdk login
Cannot reach https://<slug>.sandbox.k8s.tangovision.dev/…: fetch failed сразу после createСертификат песочницы ещё не выпущенПодождите минуту-две и повторите команду
404 от install --sandbox или пустой sandbox list для песочницы, которую создал коллегаОна принадлежит организации коллегиСм. Два разработчика, одна песочница
При входе ошибка invalid redirectХост ещё не зарегистрированПришлите нам slug (шаг 3) и дождитесь подтверждения
Забыли пароль от песочницыНа странице входа в песочницу нет ссылки для сбросаНапишите своему контакту — мы зададим новый временный пароль
Сотруднику отказано во входе сразу после кнопки staffНет в группе /sandbox-developers или учётная запись в песочнице ещё не связанаПопросите добавить вас в группу и связать вашу учётную запись в песочнице
Вход выполнен, в боковом меню «Реестр модулей недоступен — показан кэшированный список.», а /sandbox/hello после успешной установки пишет Module not in the registryУ вашей учётной записи в песочнице ещё не задан tenant_idСообщите своему контакту; мы зададим его равным organizationId вашей песочницы
Module not in the registryМодуль не установлен или slug в URL не совпадаетЗапустите sandbox install заново и перезагрузите страницу; slug в URL — часть id манифеста после module-
Module failed to loadПо зарегистрированному адресу никто не отвечает, либо это dev-сервер или 127.0.0.1Оба терминала, dev:remote и serve:remote, запущены? curl http://localhost:6001/assets/remoteEntry.js должен вернуть JavaScript; переустановите модуль ровно с этим URL
Скрипт заблокирован в SafariHTTPS-страница загружает HTTP с loopbackИспользуйте Chrome или Firefox
Внутри модуля каждый вызов API — 401Чтение localStorage['access_token']Вызывайте getAccessToken() из @tv/extension-sdk/context на каждый запрос; оболочка песочницы этот ключ не пишет
Песочница пропалаИстекла: прошёл срок, заданный при создании, плюс продленияСоздайте заново с --ttl-days=30 и пришлите нам новый slug

Ещё: Если страница пустая.

Что можно и чего нельзя ​

  • Можно создавать, сбрасывать, продлевать и удалять свои песочницы и устанавливать в них модули. Токен песочницы администрирует только её.
  • Нельзя добраться до базы другой песочницы или до продуктивной среды любой организации. Между пространством имён песочниц и продакшеном стоят NetworkPolicy, а роль базы данных вашей песочницы не может открыть базу другой песочницы или базу postgres на сервере. Но вход в песочницы пока общий: на 26.09.2026 любая песочница пускает любого пользователя общего реалма песочниц, для какой бы песочницы ни была заведена его учётная запись. См. Что изолировано, а что общее.
  • Нельзя публиковать в реестр платформы или клиентам. Такого пути пока нет; продвижение — ручная проверка со стороны Tango Vision.
  • Песочницы — общая инфраструктура с фиксированной квотой. Считайте их одноразовыми, используйте только для разработки и храните в них только синтетические данные.

Платформа для разработчиков находится в режиме preview, и песочницы не сопровождаются гарантиями доступности. Вопросы — контакту из приветственного сообщения или на developers@tango.vision.

Создано на платформе Tango Vision. Вопросы? developers@tango.vision