# DeepSeek Harness: настройка через RouterAI и генерация картинок (dsh-image-gen)

DeepSeek Harness (`dsh`) — открытый агент-харнес от DeepSeek с веб-интерфейсом: чат, рабочие пространства с файлами, инструменты (shell, файлы, веб-поиск) и плагины. Из коробки он ждёт ключ DeepSeek, но умеет работать с любым OpenAI-совместимым шлюзом.

RouterAI предоставляет совместимые с OpenAI эндпоинты `POST /api/v1/responses` и `POST /api/v1/chat/completions`, поэтому dsh подключается штатным способом — через «Custom model API» в настройках. Один ключ RouterAI даёт доступ ко всем моделям каталога: DeepSeek, Qwen, Kimi, GLM, Claude, GPT и другим.

После настройки по этому гайду в чате dsh будет работать **DeepSeek V4.1 Flash** через RouterAI, а плагин **dsh-image-gen** будет рисовать картинки моделью GPT Image 2.5 через тот же шлюз и тот же ключ.

<figure markdown="0"><img src="https://b51bc417-3ee0-451a-a83b-8a681d027a96.selstorage.ru/public/eaedefd27f51fc7cd202a2f53b2e154f.png" alt="Главное окно DeepSeek Harness: слева список сессий, в центре поле ввода, в строке инструментов выбраны OpenAI Compatible для картинок и DeepSeek V4.1 Flash для чата" width="1400" height="875"><figcaption>Главное окно dsh после настройки. В строке ввода две «таблетки»: <strong>OpenAI Compatible</strong> — провайдер картинок из плагина, <strong>DeepSeek: DeepSeek V4.1 Flash</strong> — модель чата из RouterAI.</figcaption></figure>

## Требования

* Node.js 22 или новее
* API-ключ из [личного кабинета](/settings/keys "личного кабинета") — один и тот же для чата и картинок
* Браузер на той же машине, где запущен dsh (или проброс порта через SSH)

## Запуск dsh и вход {#zapusk-dsh}

Самый короткий путь — одна команда, которая поднимает веб-интерфейс на локальном порту 3080:

```bash
npx @deepseek-ai/dsh web
```

В консоли появится строка вида `dsh web: http://127.0.0.1:3080/?token=…`. Токен обязателен: без него сервер отвечает 401. Откройте ссылку целиком — браузер получит cookie, и дальше токен в адресе не нужен.

dsh можно запускать и в Docker: образ на `node:24` с глобально установленным пакетом `@deepseek-ai/dsh`, состояние (`~/.dsh`) в томе. Ссылку с токеном в этом случае выдаёт `docker compose logs`. Для настройки разницы нет: дальше всё делается в браузере.

> ⚠ dsh принимает запросы к настройкам и хранилищу ключей только с loopback-адреса. Если открыть интерфейс по IP машины, чат работать будет, а сохранить ключ или провайдера не получится. Открывайте по `127.0.0.1` или пробрасывайте порт через SSH.

## Ключ RouterAI

Создайте ключ в [личном кабинете](/settings/keys "личном кабинете"): «Создать новый ключ». Ключ показывается один раз — сохраните его. Мастер-ключ не нужен, он только для управления ключами.

Базовый адрес API, который понадобится в обеих формах ниже:

```
https://routerai.ru/api/v1
```

## RouterAI как провайдер моделей {#podklyuchenie-provaydera}

Откройте **Settings** (внизу левой панели) → вкладка **Models**. Здесь уже есть карточка DeepSeek с красной точкой — ключа нет, её трогать не нужно. Нажмите **Add model provider**.

<figure markdown="0"><img src="https://b51bc417-3ee0-451a-a83b-8a681d027a96.selstorage.ru/public/d03d445ad2b9167076b13b73d689a93d.png" alt="Вкладка Models в настройках: карточка DeepSeek без ключа, карточка routerai с пометкой Custom и зелёной точкой, кнопка Add model provider" width="1200" height="510" loading="lazy"><figcaption>Settings → Models. Так вкладка выглядит после настройки: <strong>routerai</strong> с зелёной точкой означает, что ключ сохранён.</figcaption></figure>

В открывшейся карточке переключитесь с «Third-party model provider» на **Custom model API**. Первый режим предлагает каталог известных провайдеров (anthropic, openai, moonshotai и другие) и сам знает их адреса, но RouterAI в этом списке нет, поэтому нужен режим с ручным адресом.

<figure markdown="0"><img src="https://b51bc417-3ee0-451a-a83b-8a681d027a96.selstorage.ru/public/d31cef625e7d771913947a35c8ec242e.png" alt="Форма Custom model API: поля Provider ID, Display name, Base URL, выпадающий список API protocol, поле API key, пустой список моделей и кнопка Fetch available models" width="1200" height="1200" loading="lazy"><figcaption>Пустая форма <strong>Custom model API</strong>. Заполняется один раз, потом провайдер редактируется кнопкой Edit.</figcaption></figure>

### Поля формы

<table markdown="0">
<thead><tr>
<th>Поле</th>
<th>Значение</th>
</tr></thead>
<tbody>
<tr>
<td>Provider ID</td>
<td>
<code>routerai</code>. Постоянный идентификатор: он попадает в сессии, ссылки на ключ и настройку модели по умолчанию. Переименовать нельзя — только создать нового провайдера.</td>
</tr>
<tr>
<td>Display name</td>
<td>Любое, например <code>routerai</code>. Показывается в списках.</td>
</tr>
<tr>
<td>Base URL</td>
<td><code>https://routerai.ru/api/v1</code></td>
</tr>
<tr>
<td>API protocol</td>
<td>
<strong>OpenAI Responses</strong>. На нём проверена работа DeepSeek V4.1 Flash. Если какая-то модель через Responses отказывает, переключите на <strong>OpenAI Chat Completions</strong> — RouterAI поддерживает оба протокола.</td>
</tr>
<tr>
<td>API key</td>
<td>Ключ RouterAI. Он уходит в хранилище dsh и обратно в форму не возвращается — поле потом показывает «Configured».</td>
</tr>
</tbody>
</table>

### Шаги

1. Нажмите **Fetch available models**. dsh запросит у RouterAI список моделей (стандартный `GET /models`) и откроет окно с поиском и галочками.
2. Отметьте нужные модели и нажмите **Add selected**. Можно отметить всё, но тогда в каталог попадёт весь список RouterAI — больше пятисот моделей, включая генераторы картинок и видео, которые в чате бесполезны. Удобнее выбрать 5–10 моделей, которыми будете пользоваться.
3. Нажмите **Create provider**. Карточка появится во вкладке Models с зелёной точкой.

<figure markdown="0"><img src="https://b51bc417-3ee0-451a-a83b-8a681d027a96.selstorage.ru/public/401a8860b0e04060582ce6367f4ac5ba.png" alt="Карточка провайдера routerai в режиме редактирования: поле API key с надписью Configured, раскрытые Customized settings с Base URL https://routerai.ru/api/v1, протоколом OpenAI Responses и списком моделей" width="1200" height="1200" loading="lazy"><figcaption>Готовый провайдер после <strong>Edit → Customized settings</strong>. Ключ скрыт, адрес и протокол можно менять, список моделей редактируется построчно.</figcaption></figure>

### То же самое в конфиге

Форма пишет в файл профиля `~/.dsh/profiles/web/cordis.patch.yml`. Его можно править руками (кнопка **Open configuration file** в заголовке настроек) — сервер перечитает файл на следующем запросе. Ключ в файл не попадает: там только ссылка на переменную, сам ключ лежит в `~/.dsh/.credentials.yaml`. Фрагмент с двумя моделями:

```yaml
- id: llm-pi-ai
  name: "@deepseek-ai/dsh-llm-pi-ai"
  config:
    providers:
      routerai:
        apiKeyEnv: ROUTERAI_API_KEY
        api: openai-responses
        baseURL: https://routerai.ru/api/v1
        models:
          - id: deepseek/deepseek-v4.1-flash
            name: "DeepSeek: DeepSeek V4.1 Flash"
            contextWindow: 1048576
          - id: moonshotai/kimi-k2.7-code
            name: "MoonshotAI: Kimi K2.7 Code"
            contextWindow: 262144
```

Если шлюз отвергает запросы при верном ключе и адресе, документация dsh советует добавить на провайдера блок `compat` с `supportsDeveloperRole: false` и `maxTokensField: max_tokens`. С RouterAI это не понадобилось.

## Выбор модели по умолчанию {#vybor-modeli}

Вернитесь в чат и нажмите на название модели справа в строке ввода. Откроется меню, в нём пункт **Model** со списком и поиском. Модели сгруппированы по провайдерам: пустая группа DeepSeek и группа routerai с тем, что вы добавили. Выбранная модель становится моделью по умолчанию для новых сессий; у уже начатой сессии модель остаётся своя.

<figure markdown="0"><img src="https://b51bc417-3ee0-451a-a83b-8a681d027a96.selstorage.ru/public/dd18f42a5795d5ca221e370c5ba4752c.png" alt="Список моделей с поиском deepseek: группа DeepSeek и группа routerai, в которой отмечена DeepSeek V4.1 Flash" width="1200" height="660" loading="lazy"><figcaption>Список моделей в чате с фильтром «deepseek». Галочка у <strong>DeepSeek: DeepSeek V4.1 Flash</strong> из группы routerai.</figcaption></figure>

В примере выбрана DeepSeek V4.1 Flash: миллион токенов контекста, принимает текст и картинки, одна из самых дешёвых моделей в каталоге. Цены на момент написания:

| Модель                          | Роль        | Вход, ₽ за 1 млн токенов | Выход, ₽ за 1 млн токенов |
| ------------------------------- | ----------- | ------------------------ | ------------------------- |
| `deepseek/deepseek-v4.1-flash`  | чат и агент | 9,80                     | 19,60                     |
| `openai/gpt-image-2.5-sunburst` | картинки    | 544,44                   | по токенам картинки       |

У генераторов картинок выход считается в токенах изображения: картинка 1:1 в 1K при качестве `high` стоит около 1 800 токенов, при `max` — около 7 000 (см. [генерацию изображений](/docs/guides/overview/multimodal/image-generation "Генерация изображений")). Актуальные цены — в [каталоге моделей](/models "каталоге моделей").

## Плагин dsh-image-gen

[dsh-image-gen](https://github.com/shanliuling/dsh-image-gen "dsh-image-gen") добавляет в dsh генерацию и редактирование картинок прямо в чате, холст, пакетную «студию» и галерею. Среди провайдеров плагина есть «OpenAI-compatible (relay)» с произвольным адресом — через него плагин ходит в RouterAI по OpenAI Images API.

### Установка

Плагин ставится в профиль `web` командой dsh, которая передаёт аргументы в pnpm:

```bash
dsh plugin --profile web add dsh-image-gen@0.9.0
# в Docker:
docker compose exec dsh dsh plugin --profile web add dsh-image-gen@0.9.0
```

> ⚠ Указывайте версию явно. pnpm 11 по умолчанию не ставит релизы моложе нескольких дней, поэтому `dsh-image-gen@latest` может молча откатиться на предыдущую версию. С явной версией pnpm добавляет исключение и ставит то, что просили.

После установки перезапустите dsh. В левой панели нажмите **Plugins**: в разделе Installed появится dsh-image-gen с включённым тумблером.

<figure markdown="0"><img src="https://b51bc417-3ee0-451a-a83b-8a681d027a96.selstorage.ru/public/2f01467b487de2de731d5141f7ac11c6.png" alt="Страница Plugins: восемь официальных плагинов и раздел Installed с одним плагином dsh-image-gen, тумблер включён" width="1400" height="1086" loading="lazy"><figcaption>Страница <strong>Plugins</strong>. Официальные плагины поставляются с dsh, установленный dsh-image-gen показан ниже.</figcaption></figure>

### Настройка провайдера картинок

Нажмите на dsh-image-gen. Откроется страница плагина с блоком **Image Generation**. Сначала выберите **Default provider: OpenAI-compatible (relay)** — этого провайдера агент будет использовать по умолчанию.

<figure markdown="0"><img src="https://b51bc417-3ee0-451a-a83b-8a681d027a96.selstorage.ru/public/73eaa92912f07b94949d716a09d612e3.png" alt="Страница плагина dsh-image-gen: переключатель Default provider с выбранным OpenAI-compatible (relay), ниже список провайдеров со статусами Key missing и Key set" width="1400" height="1086" loading="lazy"><figcaption>Страница плагина. Выбран <strong>OpenAI-compatible (relay)</strong>, у него статус Key set, у остальных провайдеров ключей нет.</figcaption></figure>

Раскройте строку **OpenAI-compatible (relay)** и заполните форму:

<table markdown="0">
<thead><tr>
<th>Поле</th>
<th>Значение</th>
</tr></thead>
<tbody>
<tr>
<td>API Key</td>
<td>Тот же ключ RouterAI. Сохраняется в хранилище dsh под именем <code>DSH_IMAGE_GEN_OPENAI_COMPAT_KEY</code> и обратно не показывается.</td>
</tr>
<tr>
<td>Endpoint / Base URL</td>
<td><code>https://routerai.ru/api/v1</code></td>
</tr>
<tr>
<td>Model</td>
<td>
<code>openai/gpt-image-2.5-sunburst</code>. Кнопка <strong>Fetch models</strong> покажет только модели с выходом «image» — можно выбрать из списка. Подойдут и другие генераторы из каталога RouterAI, например Seedream или Flux.</td>
</tr>
<tr>
<td>Edit request format</td>
<td>
<strong>Standard multipart (official OpenAI)</strong>. Это формат для редактирования картинок; для генерации с нуля он не важен.</td>
</tr>
<tr>
<td>Default generation quality</td>
<td>Пусто — качество выберет модель. GPT Image 2.5 через RouterAI понимает <code>auto, low, medium, high, xhigh, max</code>; в списке доступных качеств в примере оставлены первые четыре.</td>
</tr>
<tr>
<td>Custom resolution table, extra fields</td>
<td>Пусто. Нужны только для нестандартных шлюзов.</td>
</tr>
</tbody>
</table>

<figure markdown="0"><img src="https://b51bc417-3ee0-451a-a83b-8a681d027a96.selstorage.ru/public/d3cdd0912963842873846674cf0685bf.png" alt="Раскрытая строка OpenAI-compatible (relay): поле API Key с подсказкой Leave empty to keep configured key, Base URL https://routerai.ru/api/v1, Model openai/gpt-image-2.5-sunburst, кнопка Fetch models, формат Standard multipart, список качеств auto, low, medium, high" width="1400" height="1086" loading="lazy"><figcaption>Заполненная форма провайдера. Ключ уже сохранён, поэтому поле пустое с подсказкой «Leave empty to keep configured key».</figcaption></figure>

Внизу формы две кнопки: **Test connection** проверяет ключ и адрес, **Save** сохраняет. Ниже на странице ещё два блока, которые стоит включить:

* **Save to workspace** с папкой `dsh-image-gen`: каждая сгенерированная картинка пишется файлом в рабочее пространство сессии, а не только в чат.
* **Show the image provider pill in the chat input bar**: добавляет в строку ввода «таблетку» для быстрой смены провайдера картинок, по умолчанию она выключена.

<figure markdown="0"><img src="https://b51bc417-3ee0-451a-a83b-8a681d027a96.selstorage.ru/public/e041d76a61f864b11f3d88361dd186a8.png" alt="Нижняя часть страницы плагина: остальные провайдеры без ключей, блок Workspace с включённым Save to workspace и папкой dsh-image-gen, блок Interface с включённой таблеткой провайдера, компонент dsh-image-gen в статусе Running" width="1400" height="1086" loading="lazy"><figcaption>Низ страницы плагина: сохранение в рабочее пространство, таблетка в строке ввода и статус компонента <strong>Running</strong>.</figcaption></figure>

Так выглядит эта таблетка в чате. Галочка стоит у OpenAI Compatible, рядом модель и статус ключа; у остальных провайдеров ключей нет.

<figure markdown="0"><img src="https://b51bc417-3ee0-451a-a83b-8a681d027a96.selstorage.ru/public/29464249ad6abe48c1e43d4bcf687c58.png" alt="Выпадающий список Image model в строке ввода: Gemini, OpenAI, OpenAI Compatible с галочкой и статусом Key configured, Seedream, DashScope, Grok, Zhipu GLM" width="1200" height="600" loading="lazy"><figcaption>Список <strong>Image model</strong> из таблетки в строке ввода.</figcaption></figure>

## Результат

Дальше просто пишете в чат, что нарисовать. Агент на DeepSeek V4.1 Flash сам вызывает инструмент плагина, получает картинку от RouterAI, показывает её в ответе и кладёт файл в папку `dsh-image-gen` рабочего пространства. Потом можно попросить изменить результат — плагин передаст исходник на редактирование.

<figure markdown="0"><img src="https://b51bc417-3ee0-451a-a83b-8a681d027a96.selstorage.ru/public/33c7ce73ae9de368fbe13338eb0c8a66.jpg" alt="Сессия чата: сгенерированная картинка киберпанк-коровы на неоновой улице, под ней ответ агента со ссылкой на файл image-2702ca00.jpg и описанием кадра" width="1400" height="1086" loading="lazy"><figcaption>Сессия «Cinematic cyberpunk cow on neon street»: картинка 16:9 и ответ агента со ссылкой на сохранённый файл. Внизу статистика: 1 ход, 3 шага, 30 тысяч токенов.</figcaption></figure>

Сам файл результата в полном размере — ниже. Запрос был текстовым: «cinematic cyberpunk cow on a neon street, 16:9».

<figure markdown="0"><img src="https://b51bc417-3ee0-451a-a83b-8a681d027a96.selstorage.ru/public/8551a33cc711da3591e3a6d0eaa6ec79.jpg" alt="Киберпанк-корова на мокрой неоновой улице, формат 16:9" width="1200" height="675" loading="lazy"><figcaption>«Cinematic cyberpunk cow on neon street», 16:9, 2048×1152.</figcaption></figure>

Начать можно не только с текста. Во вкладке **Studio** плагина есть бесконечный холст: набросайте рисунок от руки, выделите фигуры и попросите агента в чате раскрасить их — набросок станет основой для готовой картинки.

<figure markdown="0"><img src="https://b51bc417-3ee0-451a-a83b-8a681d027a96.selstorage.ru/public/3ff2c8c7d614387c87e48ee54a1eddb9.webp" alt="Справа вкладка Studio плагина dsh-image-gen: на бесконечном холсте чёрной линией нарисован человечек — круглая голова с волосами, платье-треугольник, волнистые руки. Слева в чате dsh готовая картинка по этому наброску: девочка в красном платье в белый горошек на цветущем лугу у озера на закате" width="1920" height="1136" loading="lazy"><figcaption>Справа набросок на холсте <strong>Infinite canvas</strong> во вкладке Studio, слева результат в чате. Агент ответил: «раскрасил всё выделенное (10 фигур: эллипс, треугольник и 8 штрихов)» — на всё ушло 30 секунд, файл сохранён в папку <code>dsh-image-gen</code>.</figcaption></figure>

## Где что лежит

| Путь                                   | Что там                                                                                                                    |
| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `~/.dsh/profiles/web/cordis.patch.yml` | Все настройки профиля web: провайдеры и модели, конфиг плагина, модель по умолчанию. Это то, что пишут формы в интерфейсе. |
| `~/.dsh/.credentials.yaml`             | Ключи. Ключ RouterAI для чата лежит под именем `ROUTERAI_API_KEY`, ключ плагина — под `DSH_IMAGE_GEN_OPENAI_COMPAT_KEY`.   |
| `~/.dsh/profiles/web/node_modules`     | Установленные плагины. Обновление — та же команда `dsh plugin --profile web add` с новой версией и перезапуск.             |
| `<workspace>/dsh-image-gen/`           | Сгенерированные картинки, если включено «Save to workspace».                                                               |
| `~/.dsh/sessions`                      | Логи сессий. Переменная `DSH_HOME` переносит весь каталог в другое место (в Docker так и сделано).                         |

Проверить, что плагин подхвачен, можно командой `dsh --profile web --dump-config`: в выводе должна быть запись `dsh-image-gen` с вашим провайдером.

## Решение проблем

### Не сохраняется ключ или провайдер (403)

Интерфейс открыт не с loopback-адреса. Откройте dsh по `http://127.0.0.1:3080` или пробросьте порт через SSH: `ssh -L 3080:127.0.0.1:3080 host`.

### Ошибка аутентификации (401)

* Убедитесь, что ключ взят из [личного кабинета](/settings/keys "личного кабинета") и активен.
* В dsh ключ хранится отдельно для чата (провайдер routerai) и для плагина (OpenAI-compatible) — проверьте оба места.

### Fetch available models ничего не находит

Проверьте Base URL: он должен заканчиваться на `/api/v1` без завершающего слеша. Модели всегда можно добавить вручную по идентификатору из [каталога](/models "каталога"), например `deepseek/deepseek-v4.1-flash`.

### После установки плагина нет раздела Image Generation

Перезапустите dsh целиком и проверьте `dsh --profile web --dump-config`. Если записи `dsh-image-gen` нет, повторите установку с явной версией.

### 402 Payment Required

Недостаточно средств на балансе. Пополните баланс в разделе [Биллинг](/settings/billing "Биллинг").

## Что дальше

* [Каталог моделей](/models "Каталог моделей") — выберите модели под задачу, в том числе генераторы картинок с выходом «image»
* [Генерация изображений](/docs/guides/overview/multimodal/image-generation "Генерация изображений") — параметры и цены моделей картинок
* [Codex](/pages/vibe-coding-codex "Вайб-кодинг в Codex") и [Claude Code](/pages/vibe-coding-claude-code "Вайб-кодинг в Claude Code") — другие агенты через RouterAI
* [deepseek-ai/deepseek-harness](https://github.com/deepseek-ai/deepseek-harness "DeepSeek Harness") — исходники и документация dsh
