diff --git a/tasks/claude-cli-proxy/DEV_TASK.md b/tasks/claude-cli-proxy/DEV_TASK.md new file mode 100644 index 0000000..308b380 --- /dev/null +++ b/tasks/claude-cli-proxy/DEV_TASK.md @@ -0,0 +1,267 @@ +# DEV TASK: Деплой CLIProxyAPI на mva154 + +**Статус:** Ready for dev +**Проект:** claude-cli-proxy +**BRD:** `tasks/claude-cli-proxy/BRD.md` + +--- + +## Цель + +Поднять CLIProxyAPI в Docker на mva154, подготовить к OAuth авторизации Claude Max подписки. После авторизации — OpenClaw сможет использовать Claude через подписку вместо API токенов. + +## Контекст + +- **CLIProxyAPI** — Go-сервер, оборачивает Claude Code CLI в OpenAI-compatible API +- **Docker image:** `eceasy/cli-proxy-api:latest` +- **Порт по умолчанию:** 8317 +- **OAuth порт (для логина):** 54545 +- **Доступ:** только из docker network (OpenClaw контейнер на том же хосте) +- **Один аккаунт**, без load balancing + +--- + +## Инфраструктура + +| Параметр | Значение | +|----------|----------| +| Сервер | `slin@82.22.50.71` (пароль: `motoZ@yaz2010`) | +| SSH | через Node.js ssh2 модуль | +| Docker network | та же сеть что у OpenClaw контейнера | +| Рабочая директория | `/home/slin/claude-cli-proxy/` | + +--- + +## Задачи + +### Task 1: Подготовка файлов на сервере + +**Шаги:** + +- [ ] **1.1** Создать директорию и config.yaml: + +```bash +mkdir -p /home/slin/claude-cli-proxy/auth +cat > /home/slin/claude-cli-proxy/config.yaml << 'EOF' +port: 8317 +remote-management: + allow-remote: false + secret-key: "" +auth-dir: "/root/.cli-proxy-api" +auth: + providers: [] +debug: false +EOF +``` + +Примечание: `auth.providers: []` — отключает проверку API key, используется OAuth токен. + +- [ ] **1.2** Создать docker-compose.yml: + +```bash +cat > /home/slin/claude-cli-proxy/docker-compose.yml << 'EOF' +version: "3.8" + +services: + cli-proxy-api: + image: eceasy/cli-proxy-api:latest + container_name: claude-cli-proxy + restart: unless-stopped + ports: + - "127.0.0.1:8317:8317" + volumes: + - ./config.yaml:/CLIProxyAPI/config.yaml + - ./auth:/root/.cli-proxy-api + networks: + - openclaw_net + +networks: + openclaw_net: + external: true +EOF +``` + +⚠️ **ВАЖНО:** Нужно узнать имя docker network где живёт OpenClaw контейнер. Проверить: +```bash +docker network ls +docker inspect --format '{{range .NetworkSettings.Networks}}{{.NetworkID}}{{end}}' +``` + +Заменить `openclaw_net` на реальное имя сети. + +- [ ] **1.3** Проверить что image скачивается: + +```bash +cd /home/slin/claude-cli-proxy +docker compose pull +``` + +**Критерий:** Файлы на месте, image скачан. + +--- + +### Task 2: Первый запуск и OAuth авторизация + +**Шаги:** + +- [ ] **2.1** Запустить контейнер в режиме логина (одноразово): + +```bash +cd /home/slin/claude-cli-proxy +docker run --rm -it \ + -p 54545:54545 \ + -v $(pwd)/config.yaml:/CLIProxyAPI/config.yaml \ + -v $(pwd)/auth:/root/.cli-proxy-api \ + eceasy/cli-proxy-api:latest \ + /CLIProxyAPI/CLIProxyAPI --claude-login --no-browser +``` + +Это выведет URL для авторизации. **Этот URL нужно передать Славе** — он откроет его в браузере и залогинится. + +⚠️ Флаг `--no-browser` обязателен (headless сервер, нет GUI). + +- [ ] **2.2** После успешного логина — проверить что токен сохранился: + +```bash +ls -la /home/slin/claude-cli-proxy/auth/ +# Должен быть файл с OAuth credentials +``` + +**Критерий:** OAuth токен сохранён в `./auth/`. + +--- + +### Task 3: Запуск сервиса + +**Шаги:** + +- [ ] **3.1** Запустить через docker-compose: + +```bash +cd /home/slin/claude-cli-proxy +docker compose up -d +``` + +- [ ] **3.2** Проверить что контейнер работает: + +```bash +docker ps | grep claude-cli-proxy +docker logs claude-cli-proxy --tail 20 +``` + +- [ ] **3.3** Проверить API: + +```bash +# Список моделей +curl -s http://127.0.0.1:8317/v1/models | python3 -m json.tool + +# Тестовый запрос +curl -s -X POST http://127.0.0.1:8317/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer dummy" \ + -d '{ + "model": "claude-sonnet-4-20250514", + "messages": [{"role": "user", "content": "Say hello, one sentence only"}], + "stream": false + }' | python3 -m json.tool +``` + +- [ ] **3.4** Проверить streaming: + +```bash +curl -s -X POST http://127.0.0.1:8317/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer dummy" \ + -d '{ + "model": "claude-sonnet-4-20250514", + "messages": [{"role": "user", "content": "Count from 1 to 5"}], + "stream": true + }' +# Должен выдавать SSE chunks +``` + +**Критерий:** API отвечает, streaming работает. + +--- + +### Task 4: Подключение к docker network OpenClaw + +**Шаги:** + +- [ ] **4.1** Определить сеть OpenClaw: + +```bash +# Найти контейнер OpenClaw +docker ps | grep -i openclaw +# Посмотреть его сеть +docker inspect --format '{{json .NetworkSettings.Networks}}' | python3 -m json.tool +``` + +- [ ] **4.2** Обновить docker-compose.yml с правильным именем сети (если отличается от `openclaw_net`) + +- [ ] **4.3** Проверить что OpenClaw контейнер видит прокси: + +```bash +# Из контейнера OpenClaw +docker exec curl -s http://claude-cli-proxy:8317/v1/models +``` + +**Критерий:** OpenClaw контейнер может достучаться до `claude-cli-proxy:8317`. + +--- + +## Проверка (Acceptance) + +| # | Проверка | Команда | Ожидаемый результат | +|---|----------|---------|---------------------| +| 1 | Контейнер запущен | `docker ps \| grep claude-cli-proxy` | STATUS: Up | +| 2 | Models endpoint | `curl http://127.0.0.1:8317/v1/models` | JSON с claude моделями | +| 3 | Chat completion | `curl POST /v1/chat/completions` | Ответ от Claude | +| 4 | Streaming | `curl POST stream=true` | SSE chunks | +| 5 | Доступ из OpenClaw | `docker exec openclaw curl ...` | Ответ от прокси | + +--- + +## Ограничения и грабли + +- ⚠️ SSH только через Node.js ssh2 (бинарный ssh сломан в контейнере OpenClaw) +- ⚠️ OAuth логин — **ручной шаг**, нужен браузер Славы. Dev готовит URL, Слава логинится. +- ⚠️ `--no-browser` обязателен при логине (headless сервер) +- ⚠️ `auth.providers: []` в config — без этого будет требовать API key +- ⚠️ Порт 8317 слушает только на 127.0.0.1 (не наружу!) +- ⚠️ Имя docker network нужно определить динамически — не хардкодить +- 🚫 НЕ открывать порт наружу +- 🚫 НЕ запускать несколько инстансов (риск бана) + +--- + +## После деплоя (делает Стрим, не Dev) + +После успешного Task 4 — Стрим добавит provider в OpenClaw config: +```json +{ + "id": "claude-cli-proxy", + "type": "openai", + "baseUrl": "http://claude-cli-proxy:8317/v1", + "apiKey": "dummy", + "models": ["claude-sonnet-4-20250514", "claude-opus-4-20250514"] +} +``` + +И назначит Dev-агенту модель через этот provider. + +--- + +## Деплой-чеклист + +- [ ] Директория и файлы созданы +- [ ] Docker image скачан +- [ ] OAuth авторизация пройдена (ручной шаг Славы) +- [ ] Контейнер запущен и отвечает +- [ ] Streaming работает +- [ ] Доступен из docker network OpenClaw +- [ ] Порт НЕ открыт наружу + +--- + +*Создано: 2026-05-14 | Автор ТЗ: Стрим | Исполнитель: Dev-агент*