От нуля до вашего модуля в вашей песочнице
От пустой папки до вашего модуля внутри 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:
corepack enable && corepack prepare pnpm@10.18.2 --activate
pnpm -v # ожидается 10.18.2Если pnpm -v показывает другую версию, значит, pnpm, установленный другим способом (через npm или Homebrew), стоит в PATH раньше; удалите его или переставьте corepack вперёд.
Затем направьте область @tv на закрытый реестр так, чтобы токен читался из переменной окружения и в самом файле секрета не было:
# ~/.npmrc
@tv:registry=https://npm.k8s.tangovision.dev/
//npm.k8s.tangovision.dev/:_authToken=${TV_NPM_TOKEN}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. Создайте каркас модуля
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, которые встретятся ниже.
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 дней, отозвать его можно там же.
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. Создайте песочницу
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| Строка | Что это |
|---|---|
id | sbx_… — идентификатор песочницы, он нужен на шаге 5 |
slug | Slug песочницы: начало её адреса; под него заводят ваши учётные записи в песочнице |
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 дней:
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. Два терминала, запускайте в таком порядке:
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):
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- Используйте Chrome или Firefox. Приглашённые разработчики входят под учётной записью в песочнице, данные которой мы прислали; при первом входе нужно задать новый пароль. Сотрудники нажимают Tango Vision staff и входят под корпоративной учётной записью.
- Вы попадаете в Building OS как Administrator, с выбранным наполненным зданием.
- Откройте
/sandbox/hello. Chrome может один раз спросить разрешение на доступ к локальной сети — разрешите. ВашShell.tsxотрисуется внутри оболочки.
Правьте, сохраняйте, перезагружайте. dev:remote пересобирает, и оболочка подхватывает новый бандл при следующей загрузке.
Два разработчика, одна песочница
Песочница принадлежит организации той учётной записи разработчика, которая её создала, а каждая учётная запись разработчика — отдельная организация. Поэтому, если над одной песочницей работают двое, тот, кто её не создавал, не достанет до неё своим ключом: sandbox list ничего не показывает, а sandbox install --sandbox=… отвечает 404. Как работать с общей песочницей:
Разработчик A создаёт песочницу (шаг 3) и, как обычно, присылает нам её slug, указав, кто ещё над ней работает. Мы заводим каждому из вас учётную запись в песочнице.
Мы присылаем разработчику B API-ключ, который действует от имени организации разработчика A. Срок его действия мы сообщим. B использует его вместо ключа с портала:
bashexport TV_API_TOKEN=tvk_... # ключ, который мы прислали разработчику B npx @tv/extension-sdk sandbox list # теперь показывает общую песочницуКлючи, которые B выпускает на портале сам, по-прежнему относятся к его собственной организации и общую песочницу не видят, а на странице портала у B песочниц не будет.
Каждый из вас отдаёт модуль со своей машины по шагам 4 и 6, на
http://localhost:6001. Запись в реестре указывает наlocalhost, а каждый браузер понимает под ним свою машину, так что каждый видит свою сборку.В песочнице одна запись реестра на модуль. Кто последним запустил
sandbox install, тот перезаписал её для обоих. Поэтому переустанавливайте модуль только при изменении манифеста, всегда с--remote-entry=http://localhost:6001/assets/remoteEntry.js, и договоритесь, какая версия манифеста актуальна.Оба ключа позволяют продлевать, сбрасывать и удалять общую песочницу, а песочница, созданная любым из них, учитывается в одном и том же лимите в 3 песочницы. Договоритесь, кто из вас этим занимается.
Когда вы замените песочницу новой, пришлите нам её slug, и мы перенастроим на неё учётные записи обоих.
Правила, которые объясняют пустые страницы
- Модуль с localhost загружает только оболочка песочницы. Продуктивная оболочка не загрузит его никогда; к клиентам ваш модуль попадает только после того, как мы проверим исходный код и соберём его в нашем CI.
- Только loopback:
localhostили127.0.0.1. Адрес в локальной сети или туннель будут отклонены. Регистрируйтеlocalhost: в macOSserve:remoteне отвечает на127.0.0.1. - Модуль отрисовывается только в вашем браузере. Коллега, открывший тот же URL, получит ошибку загрузки: localhost — это его машина (если только он не отдаёт модуль сам, см. Два разработчика, одна песочница).
- Ваш бэкенд работает на вашей машине, и браузер может к нему обращаться, а платформа — нет: у песочницы нет выхода в интернет, поэтому Copilot не достанет до MCP-эндпоинта на localhost, а Copilot песочницы не может вызвать внешнюю LLM.
- Делите
i18nextиreact-i18nextвvite.config.tsлибо оба, либо ни одного, и сохраните aliasuse-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 |
| Скрипт заблокирован в Safari | HTTPS-страница загружает 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.