# Раннер FAST AI

Раннер запускает инструменты моделей на компьютере пользователя и передаёт ответы в FAST AI. Поддерживаются Claude CLI, Grok CLI, Kimi CLI, ChatGPT/Codex, DeepSeek Harness Flash/Pro, z.ai/GLM в режимах Coding и API, а также сохранённые модели Fast. Чатовые модели без инструментов продолжают использовать серверные API.

## Установка

Нужны macOS или Linux, Python 3.11+, `curl`. На Windows используйте Ubuntu в WSL2. Для ChatGPT/Codex нужен Node.js с `npm`.

Создайте раннер в «Настройки → Runners», скопируйте одноразовый токен и выполните:

```bash
curl -fsSL https://fst-runner.fstai.xyz/install.sh | \
  FASTAI_URL=https://app.fst.ac \
  FASTAI_RUNNER_TOKEN=<твой_токен> \
  bash
```

Установщик создаёт `~/fastai-runner`, ставит зависимости и запускает пользовательскую службу: launchd на macOS, systemd на Linux или фоновый процесс, если служба недоступна. Для запуска в терминале добавьте `BACKGROUND=0` перед `bash`. После подключения привяжите раннер в FAST AI.

Полный комплект исходников доступен в [архиве](https://fst-runner.fstai.xyz/fastai-runner.zip). Распакуйте его и запустите `install.sh` с адресом сервера и токеном.

## Обновление

```bash
~/fastai-runner/update.sh
```

Токен берётся из `runner.env`, файл доступен только владельцу. Ручное обновление перезапускает службу: выполняйте команду после завершения задач. `cat ~/fastai-runner/VERSION` показывает версию.

Переход с v24 на актуальную версию выполняется этой командой один раз. Автоматический канал v24 сохранён на старой версии: его обновлятор мог прерывать задачи при появлении новых файлов. Новые установки и ручное обновление используют канал `https://fst-runner.fstai.xyz/current`. Если старый скрипт ещё берётся из кеша, обновите напрямую:

```bash
curl -fsSL https://fst-runner.fstai.xyz/current/update.sh | bash
```

В v26 самообновление проверяет SHA-256 и синтаксис Python. Оно повторно проверяет занятость после скачивания и подготовки CLI, перед заменой файлов и перезапуском. Пока раннер занят, файлы не заменяются; следующая попытка произойдёт позже.

## Модели и инструменты

Модель выбирается в обычном селекторе FAST AI. Авторизация и личные API-ключи берутся из настроек пользователя. Каталог моделей общий с сервером; раннер получает выбранный идентификатор. Недоступный движок сообщает причину в чате.

DeepSeek использует тот же Harness SDK и настройки, что на сервере. z.ai/GLM использует тот же потоковый API-клиент и исполнение инструментов. Файлы, команды и вложения находятся в `~/fastai-runner/workdir/<sid>/reports`, временные файлы — в соседней `tmp`. Отключённый или старый раннер не переносит задачу на сервер.

LLM API подключаются напрямую. Внешние запросы инструментов используют прокси сессии; при отсутствии прокси соединение блокируется. Переменные окружения задаются отдельно для каждой задачи. «Стоп» отменяет агентный запрос и текущую команду с дочерними процессами.

## Управляемые субагенты: контракт v25

Grok/Kimi ACP, Claude SDK, DeepSeek Harness и API-движки поддерживают обычные
дочерние сессии через общий bridge `fastai_agents`. Раннер объявляет capability
`managed-subagents-v2`, когда доступны bridge, HTTP/SOCKS transport и модуль
`managed_subagent_tools.py`. Прежний `codex-managed-subagents-v1` сохраняется.
Сервер проверяет capability до отправки нового режима; старые кадры работают
без managed-полей.

`remote_query`, `remote_grok_query`, `remote_kimi_query`, `remote_deepseek_query`
и соответствующие `frame_*_query_start` принимают optional параметры:

| Параметр | Значение |
| --- | --- |
| `managed_subagents` | Строго `{url, capability, parent_sid}`; `parent_sid` равен `session_id` запроса |
| `managed_workspace_session_id` | UUID корневой сессии, чья рабочая область наследуется |
| `managed_workspace_relative_cwd` | Относительный cwd внутри корневой сессии; `""` означает её корень |

Без workspace-полей сохраняется обычный cwd выбранного движка:

| Движок корневой сессии | Cwd на раннере | `relative_cwd` для всех её детей |
| --- | --- | --- |
| Claude / Grok / Kimi / Codex | `<WORKDIR_BASE>/<root_sid>` | `""` |
| DeepSeek Harness / API (GLM, z.ai, Fast) | `<WORKDIR_BASE>/<root_sid>/reports` | `"reports"` |

Провайдер ребёнка не меняет явно переданный cwd: API-ребёнок Claude работает
в root sessiondir, Claude-ребёнок DeepSeek — в `reports`. У API `workspace_root`
всегда равен `<WORKDIR_BASE>/<root_sid>`, а `tmp` — `<root_sessiondir>/tmp`.
Для ребёнка сервер передаёт оба workspace-поля по настройкам корня, не вычисляет
их из локального абсолютного `effective_cwd`. При отсутствии binding оба kwargs
имеют default `None` и не появляются в кадре. Если передан root UUID, а relative
оставлен `None`, frame нормализует его в `""`; это **не** default `reports` для API.

Для Grok/Kimi прокси берётся из существующего `session_proxy`, для Claude — из
`options.env`. У DeepSeek дополнительно есть `managed_proxy`: непустое значение
имеет приоритет над прокси из `env`. Переменные прокси процесса раннера не служат
запасным вариантом. Для удалённого MCP разрешён только `https://app.fst.ac`
с явным прокси сессии. Для SSH-work в v27 разрешён отдельный транспорт, описанный ниже. Команды, аргументы и окружение MCP от сервера не принимаются:
раннер собирает stdio-конфигурацию из локального Python и соседнего bridge.

Рабочая область ребёнка может быть общей с родителем, а история остаётся в
`workdir/<child_sid>/.grok-home`, `.kimi-home`, `.claude-home` или `.deepseek-home`.
У уже существующего корневого родителя сохраняется прежнее native-хранилище,
чтобы включение MCP не меняло каталог, из которого загружается его история.
Пути с traversal и выход через symlink отвергаются. Managed Claude получает
авторизацию в окружении отдельного процесса и не держит общий SDK-lock во время
хода: родитель может ждать одновременно работающего ребёнка.

`managed_subagent_tools.py` включён в архив, манифест, список самообновления и
download/`py_compile` установщика. Bootstrap-проверка импортирует адаптер,
проверяет его связь с bridge и готовность `managed-subagents-v2`.
Проверочная сборка без публикации:
`python3 runner/build_dist.py --output <временный-каталог>`.

## Координация: v26

При готовых bridge и API-адаптере с инструментом `yield_to_agents` раннер
также объявляет `managed-coordinator-v1`. Сервер
проверяет её перед включением `yield_to_agents`: инструмент сохраняет план
основной сессии и позволяет продолжить её по событию после завершения работников.
Результаты проверяет основная сессия и собирает один общий отчёт обычным
сообщением в главном чате. Ожидание и журнал результатов ведёт сервер FAST AI;
команды и файлы работников остаются на том же раннере в рабочей области задачи.
Для этой части нужен сервер с поддержкой координатора.

После ручного перехода с v24 дальнейшие самообновления используют канал
`/current`; занятый раннер откладывает замену файлов. Публикация не означает
мгновенного обновления всех установленных копий.

## SSH-work: v27

При выбранном SSH-work управление субагентами идёт по уже авторизованному
WebSocket раннера к FAST AI. Этот служебный канал не требует HTTP-прокси
и не передаёт SSH-ключи на компьютер пользователя. Сервер сохраняет проверки
владельца, родительской сессии, выбранного раннера и поколения хода.
Настройки SSH-work и маршрут внешних команд остаются настройками сессии.

Раннер объявляет `managed-subagents-relay-v1` только после запуска локального
relay. Конфиг сохраняет три поля; `url` принимает точный маркер
`runner-ws://fastai`. Конкретный loopback-порт назначает сам раннер, он не
принимается из серверного конфига. При обрыве или тайм-ауте результат может быть
неизвестен: автоматического повтора нет, повтор мутации требует тот же
`request_id` и те же аргументы.

Нужны v27 на компьютере и сервер с поддержкой relay. Старый раннер получает
понятное требование обновиться. Обычный HTTP/SOCKS-режим по-прежнему требует
явный прокси сессии и не переключается на прямое соединение.

## Диагностика

Логи находятся в `~/fastai-runner/logs/runner.log` и `runner.err`. Ошибка 4401 означает неправильный или удалённый токен. Повторная установка с тем же токеном обновляет существующий раннер. Две копии с одним токеном вытесняют друг друга.

## Сборка для скачивания

В репозитории FAST AI:

```bash
python3 runner/build_dist.py
```

Сценарий собирает файлы, архив, манифест с хешами и версии в `tmp/runner-dist` для проверки перед публикацией. В архив попадают только перечисленные исходники и документация; конфиги пользователя, ключи и рабочие каталоги не включаются.

Проверенный комплект публикуется в отдельный каталог `fstai-www/fst-runner/releases/`, а ссылка `current` переключается после проверки всех файлов. Корневые `manifest.json`, `version.txt`, `VERSION` и runtime-файлы остаются v24 для старых автоматических обновляторов. Корневые установщик, ручное обновление и архив ведут на актуальную версию.
