Files
admin/.wiki/concepts/omniroute-combo-deepseek-web-tuning.md

98 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: OmniRoute: настройка web-комбо под агентскую работу (deepseek-web + тулы)
type: concept
tags: [omniroute, deepseek-web, tool-calling, combo, pi, web-cookie, qwen-web, baxia-waf]
sources: [../sources/omniroute-session-2026-08-22.md]
updated: 2026-08-22
---
# OmniRoute: настройка web-комбо под агентскую работу
Диагностика и настройка комбо `deepseek-v4-flash-web` / `deepseek-v4-pro-web` (провайдер deepseek-web = веб-чат chat.deepseek.com через userToken, 3 аккаунта megan/yulia/vitya). Сессия 2026-08-22.
## Архитектура
```
pi (клиент) → omniroute (localhost:20128, Next.js + sqlite + MCP) → combo → deepseek-web executor → chat.deepseek.com/api/v0/chat/completion
```
- Веб-чат DeepSeek **не имеет нативного function calling** — omniroute **эмулирует**: сериализует `tools[]` в текстовый контракт `<tool>{"name":"...","arguments":{...}}</tool>` в промпт, модель пишет блоки текстом, парсер (`open-sse/translator/deepseekWebTools.ts`, 486 строк) разбирает зоопарк форматов обратно в OpenAI `tool_calls`.
- `toolCalling: "emulated"` в `src/shared/constants/providers/web-cookie.ts` — маркер эмуляции (claude-web = `"none"`, grok-web = нативный `true`).
- Executor: `open-sse/executors/deepseek-web.ts` (1147 строк): userToken→accessToken, PoW-челлендж, создание/удаление сессий, SSE-парсинг фрагментов (THINK/ANSWER), эмуляция тулов.
- Управление: REST `http://127.0.0.1:20128/api/combos` (GET список, PUT /api/combos/[id]). MCP-тулы omniroute в pi-сессии отваливаются с `Unknown Mcp-Session-Id` — работать через HTTP напрямую.
## Найденные причины вылетов агента (по убыванию важности)
### 1. `system_message` override убивает скилы pi ⭐
`applyComboAgentMiddleware` (`open-sse/services/comboAgentMiddleware.ts`) **удаляет ВСЕ system-сообщения от pi** (скилы, AGENTS.md, инструкции) и ставит свой `system_message` комбо. Модель физически не видит скилы.
**Фикс:** `PUT /api/combos/[id]` с `"system_message": ""` — пустая строка = override не применяется (`trim()`-проверка), промпт pi проходит.
### 2. `tool_filter_regex` режет инструменты ⭐
Было `^(bash|computer)$` — из 339 тулов pi оставалось 2, модель слепая (не могла звать read/write/edit/MCP).
**Фикс:** `^(bash|read|write|edit|grep|glob|list|describe_image|mcp__[a-z0-9_]+)$` — базовые + все MCP (filesystem, projects_meta, interns, books_ops...). Проверено: 339→25 тулов, все имена матчатся.
### 3. search-режим модели ломает tool-calling ⭐
`deepseek-v4-flash-think-search` (суффикс `-search`) включает веб-поиск чата: при URL модель сама лезет «читать» (сообщение «Link reading is unavailable in Expert Mode» — это веб-чат, не pi), генерит токены `DEEP_SEARCH`/`SEARCHING` в стриме → валидатор качества режет → `Upstream response failed quality validation: streaming upstream error`.
**Фикс:** модель в комбо → `deepseek-v4-flash-think` (без search; thinking остаётся).
### 4. `streaming upstream error` — валидатор качества
`open-sse/services/combo/validateQuality.ts` `isStreamingUpstreamError()`: SSE-фрейм с `eventType === "error"` / `parsed.error != null` / `type:"error"` до контента → стрим режется, все 3 аккаунта round-robin фейлятся → «All models failed». Через API не настраивается — патч кода.
### 5. 503 `chat_admission_busy` — лимит веб-чата DeepSeek
Перегрузка их серверов / слишком частые запросы (агентный цикл pi = серия быстрых запросов). Не настройка omniroute, а capacity провайдера.
**Фикс:** `config.maxRetries: 4`, `config.retryDelayMs: 4000` (было 12 / 15002000). Также qwen-web падал по DNS (`EAI_AGAIN chat.qwen.ai`) — сетевой глюк, не ключ.
### 6. Пустые tool_calls (`arguments: {}`, `name: undefined`)
Модель иногда генерит `<tool>{"name":"bash","arguments":{}}</tool>` без аргументов → pi-валидация падает (`command: must have required properties command`). Следствие длинного контекста + слабого контракта. Сокращение тулов (фикс №2) снижает частоту.
## Что работает после фиксов (проверено тестами)
- Эмуляция tool-calling **исправна**: тест с 1 тулом и с 25 тулами (stream=true и false) возвращает корректные `tool_calls` (`{"name":"read","arguments":{"path":...}}`).
- То, что выглядит как «модель пишет read("...") текстом» — это **`reasoning_content`** (мысли модели), pi их показывает, реальный tool_call при этом корректный.
- Скиллы видны после удаления system_message.
## Web-провайдеры с tool calling (для кастомного провайдера)
Из кода omniroute (`web-cookie.ts` + executors). Эмуляция (`"emulated"`) у: deepseek-web, qwen-web, gemini-web, chatgpt-web, kimi-web, t3-web, perplexity-web, blackbox-web, muse-spark-web, inner-ai, adapta-web. Нативный (`true`): grok-web. `"none"`: claude-web (не стоит скрейпить).
Бесплатные без подписки: **deepseek-web** (✅ есть), **qwen-web** (✅ ключ есть, DNS-глюк), **gemini-web** (Google-аккаунт), **kimi-web** (свободный лимит), **grok-web** (free-тир).
## План кастомного провайдера (идея, не реализовано)
OmniRoute для 2 комбо — overkill (Next.js + sqlite + дашборд + MCP). Идея: **вытащить** готовые `executor/deepseek-web.ts` + `translator/deepseekWebTools.ts` из omniroute (они работают), завернуть в минимальный OpenAI-совместимый сервер:
- `POST /v1/chat/completions` + `GET /v1/models` (pi подключается как провайдер)
- round-robin по аккаунтам из конфига (отдельное комбо на провайдера — **не смешивать** в одном)
- **без quality validation** (убирает все streaming upstream error)
- `persistSession: true` (переиспользование сессии → меньше 503)
- ~300 строк обвязки + 2 готовых файла
- Плюс: поддержать qwen-web / gemini-web / kimi-web / grok-web как отдельные комбо (один парсер webTools.ts, разные executors)
## Ключевые файлы omniroute
- `src/shared/constants/providers/web-cookie.ts` — реестр web-провайдеров, toolCalling
- `open-sse/executors/deepseek-web.ts` — executor веб-чата DeepSeek
- `open-sse/translator/deepseekWebTools.ts` + `webTools.ts` — эмуляция/парсинг тулов
- `open-sse/services/combo/validateQuality.ts` — валидатор качества (режет стримы)
- `open-sse/services/comboAgentMiddleware.ts` — system_message override + tool_filter_regex
- `src/shared/validation/schemas/combo.ts``updateComboSchema` (PUT-поля)
- Данные: docker volume `omniroute-data``/app/data/storage.sqlite`, логи `/app/data/logs/application/app.log`, call_logs `/app/data/call_logs/`
## Связанное
- [[admin-infra-project]] — контекст стека
- [[omniroute-session-2026-08-22]] — хронология сессии (sources)
## qwen-web: стена baxia-WAF (2026-08-22, llm-web-proxy подзадача)
Попытка добавить qwen-web в llm-web-proxy упёрлась в анти-бот:
- **Симптом:** completion возвращает HTTP 200 с JSON-эневелопом
`{"ret":["FAIL_SYS_USER_VALIDATE","RGV587_ERROR::SM::哎哟喂,被挤爆啦,请稍后重试"],"data":{"url":".../_____tmd_____/punish?x5secdata=...&action=captcha"}}`
— слайдер-капча Alibaba baxia-WAF. RGV587 = punish-flow, требует решить капчу в браузере (получить x5secdata).
- **Проверено (все — капча):** Node-fetch с полным свежим cookie-jar (включая token/cna/ssxmod_itna), со всеми браузерными заголовками (sec-ch-ua, sec-fetch-*, Accept: text/event-stream), со статическим bx-umidtoken / без него. Даже **настоящий Chrome** (CDP :9222, залогиненная сессия, капча разгадана вручную): chats/new **проходит** (браузерный фингерпринт), но chat/completions виснет → капча возвращается.
- **Вывод:** капча привязана к device-фингерпринту запроса (bx-umidtoken минтится JS из sg-wum.alibaba.com), не к cookie. Прямой API-scraping из Node — мёртвая ветка.
- **Зацепка:** «из под omniroute работает» — в **контейнере** omniroute лежит рабочая версия `open-sse/executors/qwen-web.ts` (≠ GitHub main, который портировали в lwp). Сравнить и/или взять подход оттуда (возможно решённый punish-flow / живой браузерный путь). Ключ/сессия qwen хранится в omniroute DB (provider_connections, зашифрован `enc.v1.` + STORAGE_ENCRYPTION_KEY из `/app/data/server.env`).
- Статус: подзадача [llm-web-proxy-qwen-web] 🟡 paused, next-сессия — юзер покажет рабочий подход.
- **2026-08-22 вечер: находка-подтверждение.** Аккаунт ForgetMeAI (FreeQwenApi, 212⭐) гоняет qwen через браузер и работает: чат-запрос исполняется **внутри страницы** (`page.evaluate(fetch(...))`) — запрос несёт настоящий bx-umidtoken + canvas-фингерпринт + same-origin → baxia-WAF пропускает. Плюс тяжёлый stealth-спуфинг (navigator/canvas-noise/задержки событий). Вывод: Node-fetch-путь мёртв окончательно, рабочий сценарий = браузерный executor (puppeteer/playwright). Референс: [[forgetmeai-free-web-chat-proxies]] + lwp `docs/reference/forgetmeai/`.