# Мост инструментов SDK — `$.sdk`

Подсистема для **проектов-инструментов** (прежде всего самого SDK, `sdk/`).
Игре порождать процессы не нужно, поэтому мост выключен по умолчанию.
Он включается манифестом проекта:

```json
{ "title": "Russiano2D SDK", "toolHost": true }
```

Без флага `$.sdk.available()` возвращает `false`, а вызовы отклоняются
ошибкой с подсказкой про `toolHost`. Это не второй игровой API: он запускает
**ровно два бинарника** — нативный CLI `r2d-sdk` рядом с движком и сам движок.
Произвольной командной строки нет, аргументы — массив строк без shell.

```js
const res = await $.sdk.tool(['validate', 'assets/hero.character.json']);
res.ok;          // код выхода 0 и json.ok !== false
res.json;        // ответ CLI: { ok, diagnostics: [{ code, severity, asset, … }] }

const game = $.sdk.launch(['--game', 'demos', '--headless', '--frames', '60']);
game.done.then(r => $.log('игра завершилась: ' + r.exitCode));
game.peek();     // { running, output, … } без ожидания конца
game.kill();
```

## 1. Методы

| Вызов | Смысл |
|---|---|
| `available()` | мост включён проектом |
| `paths()` | `{ tool, toolFound, engine, exeDir }` — пути бинарников |
| `tool(args, { timeout }?)` | запустить `r2d-sdk <args…>` → `Promise<результат>` |
| `launch(args, { timeout }?)` | запустить движок → `{ id, done, kill(), peek() }`; таймаут по умолчанию — без ограничения |
| `active()` | сколько процессов отслеживается |

Результат: `{ ok, exitCode, json, output, truncated, killed, error }`.
`json` — последняя строка вывода, разбираемая как объект (CLI печатает один
JSON). Если CLI не вернул JSON, `ok = false` и `error` объясняет это.

## 2. Что гарантируется

* **Кадр не блокируется:** вывод процесса читает отдельный поток, Promise
  разрешается в `tickSdk()` по игровым кадрам (до 16 процессов одновременно).
* **Таймаут:** у `tool()` — 120 с по умолчанию; процесс убивается, Promise
  завершается ошибкой `таймаут процесса`.
* **Вывод ограничен 1 МБ**, хвост сохраняется (`truncated: true`).
* **При выходе** движок убивает оставшиеся процессы.

## 3. Ограничения

* только то, что умеет `r2d-sdk` и перезапуск движка; свои бинарники запускать нельзя;
* в вебе (Emscripten) процессов нет — `available()` всегда `false`;
* окружение подпроцесса наследуется, рабочий каталог — каталог движка: пути
  передавайте абсолютными (`sdk/lib/model.js: absolutePath`).

## 4. Проверка

`tests/js/sdk_test.mjs` (очередь, таймаут, ошибки — подменённый бэкенд),
`tests/agent/sdk_shell_test.py` (настоящий `r2d-sdk` через движок),
`tests/agent/sdk_cli_test.py`. Описание SDK целиком — [../SDK.md](SDK).
