Локальный OpenAI-совместимый мост к бесплатному веб-чату DeepSeek (chat.deepseek.com), который можно подключить к opencode как обычного провайдера моделей и использовать как полноценного агента (чтение/правка файлов, bash, поиск по коду и т.д.) — без API-ключа и оплаты.
English version: README.en.md
Оригинал проекта: https://github.com/sums001/Deepseek-API Это неофициальный проект, не связанный с DeepSeek. Вы используете свой обычный аккаунт DeepSeek и несёте ответственность за соблюдение его условий.
Warning
Риск блокировки аккаунта. Мост работает через ваш обычный веб-аккаунт DeepSeek, а не через официальный API. Антифрод DeepSeek может принять работу агента за автоматизацию и временно заблокировать аккаунт — известны случаи блокировки на несколько дней после всего 4–5 быстрых запросов. Полностью исключить этот риск нельзя. Встроенные паузы, квоты и cooldown снижают вероятность, но не гарантируют защиту. Для стабильной работы используйте официальный API DeepSeek с ключом и не запускайте большие агентские сессии на основном аккаунте. Подробнее — в разделе Безопасность аккаунта.
- Как это работает
- Требования
- Единый путь развёртки (копировать целиком)
- Пошагово, с пояснениями
- Проверка работоспособности
- Куда слать запросы: URL и API-ключ
- Чат в терминале
- Интеграция с opencode
- Переключение моделей, DeepThink и веб-поиск
- Переменные окружения
- Безопасность аккаунта
- Ограничения и важные нюансы
- Обслуживание и troubleshooting
- Структура проекта
- Безопасность
- Лицензия
┌──────────────┐ OpenAI API ┌──────────────────────┐ внутренний ┌──────────────────┐
│ opencode │ ───────────────▶│ server/api.py │ ── протокол ──▶│ chat.deepseek │
│ (агент/CLI) │ localhost:8000 │ (FastAPI, /v1/...) │ + PoW/WASM │ .com (ваш аккаунт)│
└──────────────┘ └──────────────────────┘ └──────────────────┘
│
├── deepseek/auth.py (вход через браузер, сессия в session/)
└── deepseek/pow.py (решение proof-of-work через wasmtime)
- opencode думает, что общается с обычным OpenAI-провайдером.
- Мост транслирует запросы в веб-чат DeepSeek, решает PoW-челлендж
(
sha3_wasm_bg.wasmв песочницеwasmtime) и отдаёт поток токенов обратно. - Сессия входа сохраняется в
session/(в git не попадает) и обновляется автоматически примерно раз в 5 часов.
- Python 3.9+ (рекомендуется 3.11/3.12)
- Node.js 18+ — нужен только для opencode (не для моста)
- Аккаунт DeepSeek (бесплатный, тот же, что для chat.deepseek.com)
- opencode — https://opencode.ai
- ОС: Windows, macOS, Linux
Ниже — весь путь от нуля до работающего агента. Выполняйте блоки по порядку. Замените
~/projectsна удобную вам папку.
# 0. Предпосылки: Python 3.9+, Node 18+, opencode
python3 --version && node --version && opencode --version
# 1. Клон проекта
mkdir -p ~/projects && cd ~/projects
git clone https://github.com/Tsuev/opencode-deepseek.git
cd opencode-deepseek
# 2. Виртуальное окружение
python3 -m venv venv
source venv/bin/activate
# 3. Зависимости + браузер для Playwright
pip install --upgrade pip
pip install -r requirements.txt
playwright install chromium
# 4. Одноразовый вход в аккаунт DeepSeek (откроется окно браузера)
python -m deepseek.auth
# 5. Конфиг (значения по умолчанию подходят для локального запуска)
cp .env.example .env
# 6. Запуск сервера (оставьте терминал открытым)
python app.py
# -> http://127.0.0.1:8000Проверка (во втором терминале):
curl http://127.0.0.1:8000/healthz
curl http://127.0.0.1:8000/v1/modelspython --version; node --version; opencode --version
mkdir $HOME\projects; cd $HOME\projects
git clone https://github.com/Tsuev/opencode-deepseek.git
cd opencode-deepseek
python -m venv venv
.\venv\Scripts\Activate.ps1
pip install --upgrade pip
pip install -r requirements.txt
playwright install chromium
python -m deepseek.auth
Copy-Item .env.example .env
python app.pyЕсли PowerShell блокирует активацию venv:
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned(или активируйте черезvenv\Scripts\activate.batвcmd.exe).
Содержимое файлов opencode.json и .opencode/agent/*.md — в разделе
Интеграция с opencode. После их создания
перезапустите opencode.
git clone https://github.com/Tsuev/opencode-deepseek.git
cd opencode-deepseekИзолирует зависимости проекта от системного Python.
python3 -m venv venv
source venv/bin/activate # macOS/Linux
# .\venv\Scripts\Activate.ps1 # Windows PowerShellpip install -r requirements.txt
playwright install chromium # разовая установка браузераrequirements.txt тянет: playwright (вход + PoW), httpx, fastapi,
uvicorn, pydantic, python-dotenv, wasmtime, openai.
python -m deepseek.authОткроется настоящий браузер — войдите в аккаунт и пройдите капчу
(human-check). После этого токен и cookies сохранятся в session/ и будут
переиспользоваться. Сессия обновляется автоматически; повторный вход нужен,
только если она полностью истекла.
cp .env.example .envДля локального запуска значения по умолчанию подходят. Пароли в .env не
хранятся — вход выполняется вручную в браузере.
python app.py
# -> DeepSeek OpenAI-compatible API on http://127.0.0.1:8000Альтернатива через uvicorn с другим адресом:
HOST=0.0.0.0 PORT=8080 python app.py
# или
uvicorn server.api:app --host 0.0.0.0 --port 8080Чтобы сервер поднимался сам и перезапускался при падении, заведите LaunchAgent
~/Library/LaunchAgents/com.deepseek.api.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key><string>com.deepseek.api</string>
<key>ProgramArguments</key>
<array>
<string>/Users/ВЫ/root/other/Deepseek-API/venv/bin/python</string>
<string>app.py</string>
</array>
<key>WorkingDirectory</key><string>/Users/ВЫ/root/other/Deepseek-API</string>
<key>EnvironmentVariables</key>
<dict>
<key>HOST</key><string>127.0.0.1</string>
<key>PORT</key><string>8000</string>
</dict>
<key>RunAtLoad</key><true/>
<key>KeepAlive</key><true/>
<key>StandardOutPath</key><string>/Users/ВЫ/root/other/Deepseek-API/logs/server.log</string>
<key>StandardErrorPath</key><string>/Users/ВЫ/root/other/Deepseek-API/logs/server.err</string>
</dict>
</plist>mkdir -p logs
launchctl load ~/Library/LaunchAgents/com.deepseek.api.plist # включить
launchctl kickstart -k "gui/$(id -u)/com.deepseek.api" # перезапуск после правок кода
launchctl unload ~/Library/LaunchAgents/com.deepseek.api.plist # выключитьВажно: при
reload=False(как вapp.py) изменения кода подхватываются только после перезапуска — используйтеkickstart -k. Логи смотрите вlogs/server.logиlogs/server.err.
# 1) Живость
curl http://127.0.0.1:8000/healthz
# {"status":"ok"}
# 2) Список моделей
curl http://127.0.0.1:8000/v1/models
# 3) Простой чат
curl http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"deepseek-chat","messages":[{"role":"user","content":"Привет!"}]}'Python SDK:
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="unused")
r = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": "Hello!"}],
)
print(r.choices[0].message.content)Готовые примеры: examples/ (01_* — напрямую из Python, 04_*–06_* — через сервер).
Базовый адрес — http://localhost:8000/v1 (или http://127.0.0.1:8000/v1).
Порт меняется переменной PORT в .env / launchd.
| Метод | URL | Назначение |
|---|---|---|
POST |
http://localhost:8000/v1/chat/completions |
Чат; стриминг через "stream": true |
GET |
http://localhost:8000/v1/models |
Список моделей (deepseek-chat, deepseek-expert) |
GET |
http://localhost:8000/healthz |
Проверка живости (без рейт-лимита) |
API-ключ: любой. Мост не проверяет Authorization и не читает его
(server/api.py не смотрит заголовок), поэтому в SDK, где ключ обязателен
синтаксически, пишут заглушку — исторически api_key="unused". В чистом HTTP
через curl заголовок Authorization вообще не нужен.
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="unused")curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"deepseek-chat","messages":[{"role":"user","content":"Hi"}]}'Нестандартные поля (вне схемы OpenAI) передаются через extra_body:
thinking (DeepThink), search (веб-поиск), conversation_id (продолжить
диалог; при resume модель игнорируется). Лимит — RATE_LIMIT_PER_MINUTE
(по умолчанию 30/мин на IP), /healthz не считается.
chat.py — интерактивный REPL, который ходит в chat.deepseek.com напрямую
через DeepSeekClient. Сервер (app.py) для этого не нужен.
./ds # продолжить последний диалог
./ds --new # начать новый диалог
./ds --model expert # Expert — сильнее и медленнее, чем Instant
./ds --think --search # DeepThink-размышление + веб-поиск
./ds --no-think # выключить DeepThink для этого запускаВнутри чата:
| Команда | Что делает |
|---|---|
/new |
новый диалог (история на сайте сохраняется) |
/model default | /model expert |
сменить модель (модель фиксируется при создании треда, поэтому смена открывает новый диалог) |
/think |
переключить DeepThink |
/search |
переключить веб-поиск |
/status |
текущая модель и переключатели |
/exit |
выйти (работает и Ctrl-D) |
Ответ печатается по мере генерации. Строка, заканчивающаяся на \, продолжается
на следующей. Текущий диалог и настройки сохраняются в session/chat_state.json,
так что следующий запуск ./ds его продолжит.
Запуск из любой директории — поставьте shim один раз:
mkdir -p ~/bin && ln -sf "$(pwd)/bin/ds-chat" ~/bin/ds-chat
# убедитесь, что ~/bin в PATHВариант Command+L прямо в терминале Kaku — в
docs/TERMINAL_CHAT.md.
Демонстрация Command+L в Kaku (25 секунд):
Видео: docs/media/kaku-ai.mp4 — H.264/AAC,
1276×992, 1.4 МБ. Превью: docs/media/kaku-ai.png (нажмите на картинку, чтобы
открыть видео).
opencode подключается к мосту как к OpenAI-совместимому провайдеру.
Создайте opencode.json в корне вашего рабочего проекта (или в
~/.config/opencode/opencode.json для глобальной настройки):
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"local-deepseek": {
"npm": "@ai-sdk/openai-compatible",
"name": "DeepSeek (local bridge)",
"options": {
"baseURL": "http://127.0.0.1:8000/v1",
"apiKey": "unused"
},
"models": {
"deepseek-chat": {
"name": "DeepSeek Chat (Instant)",
"tool_call": true,
"reasoning": false,
"limit": { "context": 64000, "output": 8192 }
},
"deepseek-expert": {
"name": "DeepSeek Expert",
"tool_call": true,
"reasoning": false,
"limit": { "context": 64000, "output": 8192 }
}
}
}
}
}npm: "@ai-sdk/openai-compatible"— универсальный OpenAI-совместимый драйвер.apiKeyобязателен для SDK, но мост его игнорирует.modelв opencode указывается какlocal-deepseek/deepseek-chatилиlocal-deepseek/deepseek-expert.limit.context— приблизительный; уменьшите, если получаете ошибки о переполнении контекста.
{
"$schema": "https://opencode.ai/config.json",
"model": "local-deepseek/deepseek-chat",
"small_model": "local-deepseek/deepseek-chat",
"provider": { "local-deepseek": { "npm": "@ai-sdk/openai-compatible", "name": "DeepSeek (local bridge)", "options": { "baseURL": "http://127.0.0.1:8000/v1", "apiKey": "unused" }, "models": { "deepseek-chat": { "name": "DeepSeek Chat (Instant)", "tool_call": true }, "deepseek-expert": { "name": "DeepSeek Expert", "tool_call": true } } } }
}
small_modelиспользуется для служебных задач (генерация заголовков и т.п.).
Файл .opencode/agent/deepseek.md в корне рабочего проекта:
---
description: Инженерный агент на DeepSeek через локальный мост
mode: primary
model: local-deepseek/deepseek-expert
temperature: 0.3
permission:
edit: allow
webfetch: allow
bash:
"git *": allow
"*": ask
---
Ты — аккуратный инженерный агент. Сначала изучаешь код, затем предлагаешь
минимальные точечные правки. Не добавляешь комментарии без просьбы. После
изменений запускаешь линтер и тесты проекта, если они есть.mode: primary— агент доступен как основной (переключается в TUI/черезdefault_agent). Для вспомогательного агента используйтеmode: subagent.- Тело файла — это системный промпт агента.
Чтобы назначить его агентом по умолчанию, добавьте в opencode.json:
{ "default_agent": "deepseek" }opencode читает конфиг один раз при старте. Полностью закройте и заново
запустите opencode после создания/правки opencode.json и файлов агентов.
Проверка: в opencode откройте выбор модели — должны появиться
DeepSeek Chat (Instant) и DeepSeek Expert под провайдером
DeepSeek (local bridge).
У веб-чата DeepSeek нет канала function calling, поэтому мост эмулирует его
текстом: подмешивает в промпт инструкцию «ответь ровно одним блоком
```tool_calls JSON» и затем парсит ответ обратно
(server/openai_format.py). Если модель пишет прозу
вместо вызова, opencode просто печатает текст и ничего не выполняет.
Что сделано для надёжности:
- парсер принимает фенсы, JSON внутри прозы, а также нативный XML/DSML DeepSeek
(
<tool_call>,function<|tool_sep|>name); - инструкция усилена (запрет прозы + пример + напоминание в конце);
- плагин дисциплины добавляет позднюю системную инструкцию.
Диагностика: запустите сервер с DEBUG_TOOLCALLS=1 — при нераспознанном вызове
в лог (logs/server.log или stdout) попадёт сырой ответ модели.
DEBUG_TOOLCALLS=1 python app.pyПроверить мост напрямую (без opencode):
curl http://127.0.0.1:8000/v1/chat/completions -H "Content-Type: application/json" -d '{
"model": "deepseek-chat",
"messages": [{"role":"user","content":"Create a file /tmp/x.txt with hello"}],
"tools": [{"type":"function","function":{"name":"write","parameters":{"type":"object","properties":{"filePath":{"type":"string"},"content":{"type":"string"}}}}}]
}'Успех — "finish_reason": "tool_calls" и заполненный message.tool_calls.
| Что | Значение в opencode | Примечание |
|---|---|---|
| Быстрая модель | local-deepseek/deepseek-chat |
По умолчанию |
| Экспертная модель | local-deepseek/deepseek-expert |
Сильнее, медленнее |
| DeepThink (reasoning) | — | Через extra_body, см. ниже |
| Веб-поиск | — | Через extra_body, см. ниже |
Модель задаётся в opencode штатно (выбор модели или поле model в агенте).
thinking (DeepThink) и search (веб-поиск) — это не модели, а
дополнительные флаги тела запроса, которые opencode напрямую не передаёт.
Их можно включить плагином (см. ниже) либо запросами через curl/SDK:
resp = client.chat.completions.create(
model="deepseek-expert",
messages=[{"role": "user", "content": "Что нового в мире?"}],
extra_body={"thinking": True, "search": True},
)Из-за эмуляции tool calling (см. выше) модель склонна «описывать» действие вместо вызова. Плагин добавляет позднюю системную инструкцию, требующую реальных tool calls. Файл авто-подхватывается opencode без правки конфига:
- глобально:
~/.config/opencode/plugin/deepseek-tool-discipline.js - в проекте:
.opencode/plugin/deepseek-tool-discipline.js(лежит в репозитории)
export const DeepSeekToolDiscipline = async () => ({
"experimental.chat.system.transform": async (input, output) => {
if (input?.model?.providerID !== "local-deepseek") return;
output.system.push(
"CRITICAL: to act you MUST emit real tool calls; never describe the " +
"action, never print JSON/XML or a tool_calls block as visible text."
);
},
});Хуки
experimental.*помечены экспериментальными (проверено на opencode 1.18.x). Если их переименуют, плагин просто перестанет срабатывать и не сломает запуск.
thinking/search — нестандартные поля тела запроса; opencode их напрямую не
передаёт. Их можно добавить хуком chat.params (output.options.thinking = true), но не включайте reasoning по умолчанию — он ухудшает соблюдение
формата tool calls. Через curl/SDK они работают сразу:
resp = client.chat.completions.create(
model="deepseek-expert",
messages=[{"role": "user", "content": "Что нового в мире?"}],
extra_body={"thinking": True, "search": True},
)Файл .env (копия .env.example):
| Переменная | По умолчанию | Назначение |
|---|---|---|
HOST |
127.0.0.1 |
Адрес прослушивания |
PORT |
8000 |
Порт |
RATE_LIMIT_PER_MINUTE |
10 |
Лимит запросов/мин на IP клиента (/healthz не считается) |
DEEPSEEK_MIN_INTERVAL |
15 |
Минимальная пауза между запросами к DeepSeek, сек |
DEEPSEEK_JITTER |
5 |
Случайная добавка к паузе (0..N сек), чтобы не было ровного ритма |
DEEPSEEK_MAX_NEW_CHATS_PER_HOUR |
6 |
Локальный лимит новых чатов DeepSeek в час |
DEEPSEEK_MAX_NEW_CHATS_PER_DAY |
20 |
Локальный лимит новых чатов в сутки |
DEEPSEEK_MAX_GENERATIONS_PER_HOUR |
30 |
Локальный лимит генераций в час |
DEEPSEEK_MAX_GENERATIONS_PER_DAY |
200 |
Локальный лимит генераций в сутки |
DEEPSEEK_COOLDOWN_SECONDS |
3600 |
Пауза после отказа DeepSeek (403/429), сек |
CONVERSATION_REUSE |
1 |
Переиспользовать диалог вместо нового чата на каждом шаге агента |
CONVERSATION_TTL |
86400 |
Сколько секунд помнить соответствие истории и диалога |
CONVERSATION_MAX_ENTRIES |
500 |
Максимум сохранённых историй |
DEEPSEEK_APP_VERSION |
2.0.0 |
Версия веб-клиента в заголовках; обновите при изменении сайта |
DEEPSEEK_PROFILE_DIR |
— | Переиспользовать существующий профиль Chrome с активной сессией |
SERVER_INTERACTIVE_LOGIN |
1 |
Открывать окно браузера при отсутствии сессии; 0 — отдавать 503 (для headless) |
SESSION_REFRESH_ENABLED |
1 |
Фоновое обновление сессии |
SESSION_REFRESH_INTERVAL |
18000 (5 ч) |
Интервал обновления, сек (меньше SESSION_MAX_AGE = 6 ч) |
REFRESH_BROWSER_CHANNEL |
chromium-headless-shell |
Канал Playwright для headless-обновления (меньше RAM) |
REFRESH_BROWSER_CHANNEL_FALLBACK |
chrome |
Запасной канал, если headless не читает cookies; пусто — отключить |
TOOLCALL_MAX_CONTINUATIONS |
3 |
Сколько раз допрашивать модель «продолжи», если tool call обрезан лимитом вывода |
DEBUG_TOOLCALLS |
— | 1 — писать в лог сырой ответ модели, если вызов не распознан |
Пример:
HOST=0.0.0.0 PORT=8080 RATE_LIMIT_PER_MINUTE=60 python app.pyМост использует обычный веб-аккаунт DeepSeek, а не официальный API. Антифрод DeepSeek может принять серию запросов агента за автоматизацию и временно заблокировать аккаунт — на практике встречались блокировки на несколько дней после всего 4–5 быстрых запросов. Полностью исключить этот риск нельзя: это ограничение самого подхода, а не баг, который можно «дописать». Официальный API с ключом — единственный вариант без такого риска.
DeepSeek видит не «opencode», а HTTP-запросы к внутреннему API веб-чата. Эвристики антифрода (точный набор не публикуется) обычно реагируют на совокупность признаков:
- Высокая частота и ровный ритм. Агент делает запросы один за другим, без пауз, характерных для человека.
- Поток новых чатов. Обычный OpenAI-клиент не умеет передавать наш
conversation_id, поэтому без отдельной логики каждый шаг агента создавал бы новый диалог. Для DeepSeek это один из самых явных признаков бота. - Несовпадающий fingerprint. Одинаковые для всех пользователей locale, timezone и версия клиента выглядят подозрительно.
- Массовые автоматические промпты. Большой системный промпт с описанием инструментов и машинно-сгенерированные tool-call блоки.
- Повторные запросы после отказа. Ретраи после
403/429могут превратить временное ограничение в длительную блокировку.
- Пауза между запросами.
DEEPSEEK_MIN_INTERVAL+ случайныйDEEPSEEK_JITTER; запросы выполняются строго по одному, параллельные агенты встают в очередь (server/safety.py,UpstreamGate). - Локальные квоты.
DEEPSEEK_MAX_*ограничивают число новых чатов и генераций в час/сутки. Счётчики сохраняются вsession/usage.jsonи переживают перезапуск (BudgetGuard). Исчерпали квоту — мост отвечает429локально, не обращаясь к DeepSeek. - Стоп при отказе. На первый
403/429мост ставит паузуDEEPSEEK_COOLDOWN_SECONDS(по умолчанию 1 час) и больше не трогает аккаунт. Пауза сохраняется вsession/cooldown.json; чтобы снять её вручную, удалите файл (Cooldown). Автоматических ретраев после отказа нет. - Переиспользование диалога. Вместо нового чата на каждый шаг агента мост
находит предыдущий диалог по присланной истории и отправляет только новые
сообщения (
server/conversations.py). Это убирает главный сигнал автоматизации — поток новых чатов — и заодно экономит контекст. - Честный fingerprint. Locale,
accept-languageи timezone берутся из браузера при входе (deepseek/auth.py), а не захардкожены одинаковыми для всех. Версию клиента можно обновить черезDEEPSEEK_APP_VERSION.
- Запускайте один агент/сессию за раз; параллельные сессии только увеличивают риск.
- Не поднимайте
DEEPSEEK_MAX_*,RATE_LIMIT_PER_MINUTEи не уменьшайтеDEEPSEEK_MIN_INTERVALбез необходимости: значения по умолчанию подобраны как компромисс между безопасностью и скоростью. - Для экспериментов и больших задач используйте отдельный аккаунт, а не основной.
- После
403/429не перезапускайте цикл запросов и не удаляйтеsession/cooldown.jsonсразу — дождитесь окончания паузы. - Для стабильной ежедневной работы переходите на официальный API DeepSeek (платный ключ): мост тогда не нужен, а блокировки аккаунта не возникает.
- Остановите мост и все агенты, которые к нему обращаются.
- Не создавайте новые сессии и не пытайтесь обойти блокировку с того же аккаунта.
- Дождитесь окончания блокировки (обычно несколько дней).
- После разблокировки начните с консервативных настроек и одного агента.
- Если повторится — используйте официальный API или другой аккаунт.
Ответственность. Проект неофициальный и не гарантирует отсутствие блокировок. Используя веб-аккаунт для автоматизации, вы принимаете этот риск и отвечаете за соблюдение условий использования DeepSeek.
- Сериализация запросов. Один общий аккаунт, PoW-хранилище
wasmtimeне реентерабельно, поэтому апстрим-вызовы выполняются по одному (см.server/api.pyиserver/safety.py). Параллельные запросы встают в очередь — не стоит запускать несколько агентов/сессий одновременно. - Tool calling эмулируется. Мост буферизует ответ и парсит его в tool
calls (
server/openai_format.py,parse_tool_calls). Парсер терпим к прозе, фенсам и XML/DSML DeepSeek, но это всё равно менее надёжно, чем нативный API: возможны сбои на длинных многошаговых цепочках. Помогает плагин дисциплины иDEBUG_TOOLCALLS=1для диагностики. - Нет реального подсчёта токенов.
usage— грубая оценка ~4 символа/токен. - Большинство OpenAI-параметров игнорируется (
temperature,top_p,max_tokensи т.д.). Действуют толькоmodel,messages,stream,conversation_id,thinking,search. - Vision не поддерживается (нет загрузки изображений).
- Идентификатор диалога.
conversation_idфиксирует модель при создании потока; при продолженииmodelигнорируется. - Лимит рейта. Локальный
429(квота, cooldown илиRATE_LIMIT_PER_MINUTE) означает «подождите», а не «повторите сразу». ОфициальныйopenaiSDK делает backoff автоматически, но приDEEPSEEK_COOLDOWN_SECONDSповторы всё равно бесполезны до истечения паузы. - Не хаммерьте аккаунт. Это ваш обычный аккаунт DeepSeek; массовые автоматические запросы могут привести к блокировке. Встроенные паузы и квоты — страховка, а не разрешение поднимать лимиты без необходимости.
Сессия истекла / 503 login_required
python -m deepseek.auth # войдите зановоУбедитесь, что SERVER_INTERACTIVE_LOGIN=0 на headless-деплое, а окно входа
выполнено заранее.
hCaptcha бесконечно перезапускается / «try again»
Начиная с этой версии python -m deepseek.auth делает ровно один переход
на страницу входа и больше не навигирует. Раньше помощник открывал
chat.deepseek.com, ждал 2 секунды и, не увидев токен, уводил на /sign_in —
это могло прервать уже начатую проверку hCaptcha и запустить её заново.
Что делать:
- Запустите
python -m deepseek.authи решайте капчу в том же окне. Не перезагружайте страницу и не закрывайте окно. - Если на странице есть кнопка входа — нажмите её сами; помощник специально не делает дополнительных переходов.
- Дождитесь окончания: на ручной вход отводится до 5 минут.
- Если цикл повторяется: закройте окно, убедитесь, что другой
Chrome/Chromium не использует
DEEPSEEK_PROFILE_DIR, и попробуйте ещё раз. По умолчанию используется установленный Chrome, а не встроенный Chromium — это меньше похоже на автоматизацию. - Не пытайтесь решать hCaptcha программно: это не поддерживается и повышает риск блокировки аккаунта. Если проверка не проходит, подождите и попробуйте позже.
Playwright Sync API inside the asyncio loop
Не вызывайте синхронный Playwright из event loop — мост уже оборачивает вызовы
в run_in_threadpool. Такое сообщение обычно означает нестандартную
модификацию кода.
Ошибки PoW / wasmtime
pip install --upgrade wasmtimeПустая headless-сессия (macOS, Chrome-профиль)
По умолчанию фолбэк на chrome. Оставьте REFRESH_BROWSER_CHANNEL_FALLBACK=chrome
или задайте DEEPSEEK_PROFILE_DIR.
429 Too Many Requests
Сначала посмотрите текст ошибки. Если это локальная квота или cooldown —
подождите (файлы session/usage.json и session/cooldown.json) и не
перезапускайте цикл запросов. Если это RATE_LIMIT_PER_MINUTE — повышайте его
осторожно. Ретраи с backoff помогают только для кратковременных сетевых
ошибок, но не снимают локальную паузу.
Порт занят
PORT=8080 python app.pyи укажите http://127.0.0.1:8080/v1 в baseURL провайдера opencode.
Агент отвечает текстом, но файлы не меняет (нет tool calls)
- В
opencode.jsonу моделей должно быть"tool_call": true. - Проверьте мост напрямую
curl-запросом сtools(см. Интеграция с opencode): должен вернуться"finish_reason": "tool_calls"и непустойmessage.tool_calls. - Поставьте плагин
deepseek-tool-discipline.js(глобально или в проект). - Запустите сервер с
DEBUG_TOOLCALLS=1и изучите сырой ответ модели в логе. - Увеличьте
stepsу агента и используйтеdeepseek-expert.
Правки кода не применились после редактирования (launchd)
Сервер под launchd с reload=False — перезапустите его:
launchctl kickstart -k "gui/$(id -u)/com.deepseek.api".
Изменения в opencode.json/агентах не применились
Перезапустите opencode — конфиг не перезагружается на лету.
| Путь | Назначение |
|---|---|
app.py |
Точка входа — запускает сервер |
deepseek/ |
Ядро: DeepSeekClient, вход (auth.py), HTTP-драйвер (client.py), PoW (pow.py) |
server/ |
FastAPI OpenAI-совместимый сервер (api.py, config.py, openai_format.py — парсер tool calls, ratelimit.py, schemas.py) |
.opencode/plugin/ |
Плагин дисциплины инструментов для opencode |
examples/ |
Запускаемые примеры (прямой Python и через сервер) |
session/ |
Сохранённая сессия (cookies + токен), git-ignored |
logs/ |
Логи launchd-сервиса, git-ignored |
.env.example |
Шаблон конфигурации |
requirements.txt |
Python-зависимости |
- Всё в
session/(cookies + bearer-токен) остаётся на вашей машине и исключено из git (.gitignore). Никогда не коммитьтеsession/. - Пароли/секреты в
.envне хранятся — вход выполняется вручную в браузере. - При
HOST=0.0.0.0мост доступен в сети без аутентификации. Биндитесь только на127.0.0.1или закрывайте firewall'ом/прокси. - Не публикуйте
session/и.envв публичных репозиториях.
MIT License. Проект неофициальный; вы отвечаете за соблюдение условий использования DeepSeek.
Оригинал: https://github.com/sums001/Deepseek-API
