From f2930f6e378cc6d54ea460ef74ab1dc22ece8669 Mon Sep 17 00:00:00 2001 From: vitya Date: Sat, 22 Aug 2026 14:01:53 +0300 Subject: [PATCH] docs(tasks): add llm-web-proxy spec (web-LLM provider for pi+Claude Code) + omniroute tuning wiki --- .tasks/STATUS.md | 14 ++- .tasks/llm-web-proxy.md | 105 ++++++++++++++++++ .../omniroute-combo-deepseek-web-tuning.md | 84 ++++++++++++++ .wiki/index.md | 2 + .wiki/log.md | 2 + .wiki/sources/omniroute-session-2026-08-22.md | 42 +++++++ 6 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 .tasks/llm-web-proxy.md create mode 100644 .wiki/concepts/omniroute-combo-deepseek-web-tuning.md create mode 100644 .wiki/sources/omniroute-session-2026-08-22.md diff --git a/.tasks/STATUS.md b/.tasks/STATUS.md index ad1f723..c33808a 100644 --- a/.tasks/STATUS.md +++ b/.tasks/STATUS.md @@ -1,9 +1,21 @@ # Admin Task Board -_Updated: 2026-08-22 — 🟢 **[sched-pipelines-local-stack] ЗАКРЫТА** (ритуал закрытия, решение vitya): мок-кампания финализирована ранее (0.1.0 published оба воркера, повторные раны noop, 0.2.0-кейс проверен симуляцией и откачен; фикс #7 httpGet fetch-Response контракта принят). Реальный деплой apilki — за отмашкой юзера (в «Спроси user'а»); VDS-миграция — таска sched-vds-deploy (paused). Wiki: +2 концепта в shared (verdaccio-token-buildkit-secret, msys-no-pathconv-docker-windows). +_Updated: 2026-08-22 — ⚪ **[llm-web-proxy] заведена** (спека .tasks/llm-web-proxy.md: кастомный web-LLM провайдер для pi + Claude Code — web-чаты, эмуляция тулов, без оверкилла omniroute; делать в следующей сессии). 🟢 **[sched-pipelines-local-stack] ЗАКРЫТА** (ритуал закрытия, решение vitya): мок-кампания финализирована ранее (0.1.0 published оба воркера, повторные раны noop, 0.2.0-кейс проверен симуляцией и откачен; фикс #7 httpGet fetch-Response контракта принят). Реальный деплой apilki — за отмашкой юзера (в «Спроси user'а»); VDS-миграция — таска sched-vds-deploy (paused). Wiki: +2 концепта в shared (verdaccio-token-buildkit-secret, msys-no-pathconv-docker-windows). _Updated: 2026-08-21 — 🟢 **[sched-fnf-daemon-image-storage] F&F ЗАКРЫТ: 7/7 + фиксы F1/F2/N1/N2 ПРИНЯТЫ** (их письмо 23:40Z, commit e755b52, daemon 0.10.1). Ретест затронутых поверхностей на `registry.kzntsv.site/sched-daemon:0.10.1` (digest 269093a08f6e…): F1 — 0.10.1 стартует против исправленного `deploy/tasks.json` (schedules); F2 — рецепт из доков (BuildKit secret + npmMinimalAgeGate:0) собран 1-в-1, history 0 JWT, storage-mongo 0.4.0, +смоук ступени 4 (коллекции, ран); N2 — баннер `storage=custom module=./my-storage.mjs` (тест пинит module=); N1 — нота MSYS_NO_PATHCONV в доках. Регресс 1/2/3/5 на 0.10.1 — тексты фейлов идентичны. Акцепт: `sched/.agents/inbox/2026-08-21T23-41-30Z-admin.md`. _Updated: 2026-08-21 — 🟢 **[sched-fnf-daemon-image-storage] F&F 7/7 PASS** (их письмо 23:12Z, таска sched 🟢 done). Образ `registry.kzntsv.site/sched-daemon:0.10.0` из опубликованного `@sched/daemon` + storage-композиция: 1) sqlite-дефолт баннер `storage=sqlite db=…` + раны в sqlite; 2) XOR `--storage mongo --db x.db` → точный отказ; 3) env fail-fast ДО старта (`MONGO_URL is not set`); 4) mongo-композицию собрал САМ (BuildKit secret, `@sched/storage-mongo@0.4.0` из verdaccio) → коллекции sched_tasks/runs/schedules + ран в mongo, баннер `storage=mongo db=…`; 5) missing-адаптер → хинт `add @sched/storage-mysql to your image`; 6) BYO `./my-storage.mjs` (MemoryStorage-порт пинового референса) → `storage=custom`, негатив без createStorage → точная ошибка контракта; 7) креды в connstring → весь лог = 1 строка баннера, 0 утечек. Находки: **F1** `deploy/tasks.json` (монтируется docker-compose.dev.yml, док. в 13.self-hosting) на старом ключе `schedule` → daemon 0.10.0 fatal (док. `docker compose up` не стартует); **F2** рецепт производного образа в 13.self-hosting без `ARG VERDACCIO_TOKEN` → YN0041 anonymous-auth при сборке 1-в-1 по докам; при фиксе через --build-arg токен оседает в image history (видно в их `schedd-mongo:0.10.0`; моя secret-сборка — 0 вхождений). N1: на винде git-bash нужен `MSYS_NO_PATHCONV=1` (иначе /app/… → `C:/Program Files/Git/…`). N2: BYO-баннер `db=default`. Репорт: `sched/.agents/inbox/2026-08-21T23-27-41Z-admin.md`. Стенд: `.tmp/fnf-daemon-image/` (gitignored), mongo-стенд возвращён в исходное. _Updated: 2026-08-20 — 🟡 **[sched-pipelines-local-stack]** schedd **0.9.0 применён + cancel-тест ЗЕЛЁНЫЙ**. **Мок-publish: режект #7 ozon** — фиксы #1-#6 приняты: npm ✅ create ✅ clone ✅ commit ✅ push fast-forward ✅ (2-й ран), release-409 ветка добавлена. 7-й баг: 409-ветка падает на стенде — `GET existing → 200` throw, т.к. прод httpGetFn=fetch отдаёт Response (.body=ReadableStream), а тест мокал `{body:{id:42}}` — разрыв тест/прод #2 (как режект #2, только httpGet). Gitea реально отдаёт id:114. Письмо 00:05Z. Ждём фикс #7. +## ⚪ [llm-web-proxy] — кастомный web-LLM провайдер для pi + Claude Code (web-чаты, эмуляция тулов, без оверкилла omniroute) + +**Status:** ready +**Where I stopped:** (not started) — дизайн готов: .tasks/llm-web-proxy.md (спека) + .wiki/concepts/omniroute-combo-deepseek-web-tuning.md (диагноз). Существующий llm-router-failover-proxy (порт 8787) НЕ подходит — это пасsthrough для API, без web-протокола/эмуляции тулов//v1-messages. +**Next action:** вытащить из docker-контейнера omniroute (`/app/open-sse/`): executors/deepseek-web.ts + translators (deepseekWebTools.ts, webTools.ts, claude-to-openai.ts, openai-to-claude.ts); собрать скелет src/server.js (`/v1/chat/completions` + `/v1/messages` + `/health`) с round-robin и логированием (req/tool-prompt/raw-reply/parse/upstream/session/stream/failover). +**Branch:** master +**Weight:** needs-claude +**Notify:** OpeItcLoc03/admin + + +--- + ## 🟢 [sched-pipelines-local-stack] — локальный стенд: sched daemon + ym/ozon воркеры + browser/ntfy/alert-bridge, потом VDS **Status:** done **Closing note:** ЗАКРЫТА 2026-08-22 (ритуал закрытия, решение vitya). Мок-кампания финализирована ранее: оба воркера publish 0.1.0, повторные раны noop, кейс «спека→0.2.0» проверен симуляцией и откачен; фикс #7 (httpGet fetch-Response контракт) принят. Реальный деплой (npmjs + github.com) — отдельное решение юзера, в «Спроси user'а» handoff'а; VDS-миграция — таска sched-vds-deploy (paused). diff --git a/.tasks/llm-web-proxy.md b/.tasks/llm-web-proxy.md new file mode 100644 index 0000000..8db243f --- /dev/null +++ b/.tasks/llm-web-proxy.md @@ -0,0 +1,105 @@ +# llm-web-proxy + +## Goal + +Кастомный LLM-провайдер (локальный, Windows) для pi и Claude Code: **web-чаты вместо API**. Основа — код omniroute (executor'ы + трансляторы), вытащенный и завёрнутый в минимальный сервер. Решает боль текущих комбо omniroute: quality validation режет стримы, 503 chat_admission_busy, оверкилл Next.js+sqlite+дашборд ради 2 комбо. + +Заказчик: vitya. Сессия дизайна 2026-08-22 (.wiki/concepts/omniroute-combo-deepseek-web-tuning.md). + +## Почему (контекст) + +- pi ходит в omniroute (localhost:20128) → combo `deepseek-v4-flash-web` / `deepseek-v4-pro-web` → провайдер `deepseek-web` (chat.deepseek.com через userToken, 3 аккаунта: megan/yulia/vitya). +- Веб-чат DeepSeek **не имеет нативного function calling** — omniroute эмулирует: `tools[]` → текстовый контракт `{"name":"...","arguments":{...}}` в промпт → парсит ответ обратно в `tool_calls`. +- Существующий `llm-router-failover-proxy` (служба, порт 8787) — **не подходит**: пасsthrough для API-провайдеров (routerai/официальный DS), нет web-протокола, нет эмуляции тулов, нет `/v1/messages`. +- Диагноз вылетов в omniroute: (1) `system_message` override режет скилы pi, (2) `tool_filter_regex` режет тулы, (3) search-режим генерит DEEP_SEARCH-мусор, (4) quality validation (`isStreamingUpstreamError`) режет стрим на `type:error`, (5) 503 = capacity веб-чата. Всё, кроме 503, — следствие оверкилла; в кастомном провайдере этих слоёв просто не будет. + +## Архитектура + +``` +pi ── /v1/chat/completions (OpenAI) ──┐ +Claude Code ── /v1/messages (Anthropic) ──┴──▶ llm-web-proxy (localhost:8788) + │ 1. detect format (openai | claude) + │ 2. round-robin: combo → account (конфиг) + │ 3. web executor: auth(PoW) → session → SSE + │ 4. эмуляция тулов: -контракт → tool_calls + │ 5. ретраи/cooldown на 429/5xx/timeout + ▼ + chat.deepseek.com (и др. web-чаты) +``` + +### Комбо (конфиг, один на провайдера — НЕ смешивать) + +- `deepseek-flash-web` → deepseek-web аккаунты (megan/yulia/vitya), модель `deepseek-v4-flash-think` (search ВЫКЛЮЧЕН — он ломал тулы) +- `deepseek-pro-web` → те же аккаунты, `deepseek-v4-pro` +- позже: `qwen-web`, `gemini-web`, `kimi-web`, `grok-web` — отдельные комбо, свои executors + +## Что берём из omniroute (готовое, работает) + +Из docker-контейнера `omniroute` (`/app/`), образ `diegosouzapw/omniroute:latest`: + +1. `open-sse/executors/deepseek-web.ts` (1147 строк) — auth userToken→accessToken, PoW-челлендж, создание/переиспользование сессий, SSE-парсинг фрагментов (THINK/ANSWER), эмуляция тулов. **Взять целиком**, удалить лишнее (persistSession уже есть). +2. `open-sse/translator/deepseekWebTools.ts` (486 строк) + `open-sse/translator/webTools.ts` — парсеры зоопарка ``-форматов. Взять целиком. +3. `open-sse/translator/request/claude-to-openai.ts` + `open-sse/translator/response/openai-to-claude.ts` — конвертация Anthropic ⇄ OpenAI (для Claude Code). +4. Зависимости: `@omniroute/open-sse` имеет свои импорты — вытаскивать вместе с нужными модулями (`streamHelpers`, `tokenAccounting` и т.п.) либо скопировать файлы в свой пакет и починить импорты. **Решение исполнителя**, но НЕ переписывать логику. + +## Что пишем сами (мало) + +- `src/server.js` — HTTP: `POST /v1/chat/completions` (OpenAI) + `POST /v1/messages` (Anthropic, с SSE keepalive `event: ping` — Claude Code рвёт соединение при долгом промпте) + `GET /health`. +- `src/router.js` — round-robin по аккаунтам + cooldown/circuit (паттерн llm-router-proxy `src/router.js` — уже написан, работает). +- `config/web-providers.json` — комбо → аккаунты → модель. Ключи НЕ в конфиге: userToken'ы из `~/.pi/agent/auth.json` или отдельного файла (формат на усмотрение, gitignore). +- **Логирование — первоклассное требование** (см. ниже). + +## Логирование (обязательно, для диагностики агентом) + +Файл-лог, **одна строка = одно событие**, grep-парсится: `[TS] [TAG] event=... key=value`. + +| Событие | Что пишем | Зачем | +|---|---|---| +| `req` | alias, аккаунт, модель, msgs, tools, stream | какой аккаунт крутит round-robin | +| `tool-prompt` | tools=N, bytes контракта | контракт раздулся → модель теряет формат | +| `raw-reply` | **первые ~500 символов сырого ответа модели** | видно ``-блоки, DEEP_SEARCH-мусор, reasoning, пустоту — корень 90% проблем | +| `parse` | calls=N, имена тулов, аргументы валидны | парсер нашёл/потерял вызовы, `arguments:{}` | +| `upstream` | статус, код (401/429/503), PoW, таймаут, ретрай N | лимиты, баны | +| `session` | created/reused/deleted, persist | эффективность persistSession | +| `stream` | complete/truncated/error, байты, длительность | обрыв стрима | +| `failover` | упавший апстрим → куда ушёл | round-robin честен | + +Правила: тела user-сообщений НЕ логируем (только размеры); `raw-reply` обрезанный; ротация (`.1`, `.2`); пишем в stdout + файл (winsw). + +## Требования + +1. **OpenAI-совместимый** `/v1/chat/completions` — pi подключается одним провайдером в `~/.pi/agent/models.json`. +2. **Anthropic-совместимый** `/v1/messages` — Claude Code подключается через `ANTHROPIC_BASE_URL=http://127.0.0.1:8788` (+ свой API-ключ, любой). +3. **Tool-calls работают** в обоих форматах: несколько последовательных инструмент-раундов (как pi вызывает тулы; Claude Code — `tool_use` блоки). +4. **thinking/reasoning** deepseek не ломается (reasoning_content для pi, `thinking`-блоки для Claude Code). +5. **Failover**: 429/5xx/таймаут/сеть → следующий аккаунт в комбо; cooldown + circuit-breaker на упавший аккаунт. +6. **persistSession: true** — переиспользование сессии (меньше 503 chat_admission_busy). +7. **БЕЗ quality validation** — этого слоя в omniroute нет (это и была боль). +8. **Логирование** — по спеке выше; агент должен по логу восстанавливать цепочку запроса. +9. **Конфиг** — JSON: комбо → упорядоченные аккаунты (baseUrl/executor, userToken-ref, model, timeout), router-параметры. +10. **Тесты**: TDD — round-robin, failover, парсинг `` (валид/зоопарк форматов), claude⇄openai конвертация, стриминг. + +## Acceptance + +- [ ] pi → `/v1/chat/completions` (model=deepseek-flash-web): стриминг, tool-calls в несколько раундов, reasoning не ломается. +- [ ] Claude Code → `/v1/messages`: подключается, тулы (`tool_use`) работают, SSE keepalive не даёт оборвать соединение. +- [ ] Failover доказан тестом: аккаунт недоступен (503/таймаут) → запрос обслуживает следующий; cooldown работает. +- [ ] Лог: по `raw-reply` + `parse` видно каждый tool-call модели; тела пользователя отсутствуют. +- [ ] Инструкция pi-интеграции (models.json) + Claude Code (env) + запуск/остановка (winsw-сервис, паттерн llm-router). +- [ ] Деплой: локально, Windows, winsw-сервис `llm-web-proxy`, живой smoke. + +## Деплой + +Локально на Windows: Node-процесс + winsw-сервис (паттерн agents-task-runner / llm-router уже обкатан). Ключи не уходят с машины. Порт 8788 (не конфликтует с llm-router :8787). + +## Обязательные скилы — вызвать до начала работы + +- invoke `tdd-criteria` — до написания кода +- invoke `using-tasks` — статус задачи +- invoke `project-discipline` — коммиты/пуши +- invoke `using-wiki` после закрытия — обновить концепт + +**TDD:** да — failover/приоритет/парсинг/конвертация это чистые юнит-кейсы; тест-харнесс обязателен (мок-апстрим). +**Разрешения:** интерны: да | автопуш: да +**Weight:** needs-claude +**Notify:** OpeItcLoc03/admin diff --git a/.wiki/concepts/omniroute-combo-deepseek-web-tuning.md b/.wiki/concepts/omniroute-combo-deepseek-web-tuning.md new file mode 100644 index 0000000..4585a14 --- /dev/null +++ b/.wiki/concepts/omniroute-combo-deepseek-web-tuning.md @@ -0,0 +1,84 @@ +--- +title: OmniRoute: настройка web-комбо под агентскую работу (deepseek-web + тулы) +type: concept +tags: [omniroute, deepseek-web, tool-calling, combo, pi, web-cookie] +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[]` в текстовый контракт `{"name":"...","arguments":{...}}` в промпт, модель пишет блоки текстом, парсер (`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` (было 1–2 / 1500–2000). Также qwen-web падал по DNS (`EAI_AGAIN chat.qwen.ai`) — сетевой глюк, не ключ. + +### 6. Пустые tool_calls (`arguments: {}`, `name: undefined`) +Модель иногда генерит `{"name":"bash","arguments":{}}` без аргументов → 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) diff --git a/.wiki/index.md b/.wiki/index.md index 9d0762c..5ccf64e 100644 --- a/.wiki/index.md +++ b/.wiki/index.md @@ -21,6 +21,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever - [windows-recovery-host](entities/windows-recovery-host.md) — Windows Recovery Host (рабочий PC пользователя) ## Concepts +- [omniroute-combo-deepseek-web-tuning](concepts/omniroute-combo-deepseek-web-tuning.md) — настройка web-комбо под агента: system_message убивает скилы pi, tool_filter_regex режет тулы, search-режим ломает tool-calling, 503 chat_admission_busy, эмуляция `` работает, план кастомного провайдера - [sched-admin-client-openapi](concepts/sched-admin-client-openapi.md) — F&F раунды 2026-08-18: Python-клиент одной командой из спеки (openapi-generator 7.24.0); r1 0.1.2 — 24/24+smoke 19/19, находки F-1..F-5 (8 операций на raw-обходе); r2 0.2.0/0.3.5 — все 5 закрыты, raw_ops удалён, 11/11 typed-only, вердикт «claim подтверждён полностью» - [openapi-generator-3-1-spec-gotchas](concepts/openapi-generator-3-1-spec-gotchas.md) — генерация клиентов из 3.1-спеки (openapi-generator 7.24.0, python): wrapped-ответы {} → ValidationError (raw-обход историчен: r2 спека фикснута), const:true → строковый enum, oneOf+discriminator → actual_instance=None (r2: плоская схема), java из PATH а не JAVA_HOME, InlineObjectN-имена, info.version не бьётся - [nvm-junction-ismain-gate-gotcha](concepts/nvm-junction-ismain-gate-gotcha.md) — ESM isMain-гейт молча не выполняется под junction'нутым npm-рутом (nvm/mise/volta); realpath-фикс; диагностика за 30 сек @@ -96,6 +97,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever ## Sources +- [omniroute-session-2026-08-22](sources/omniroute-session-2026-08-22.md) — хронология сессии настройки omniroute web-комбо (deepseek-web): корни вылетов, фиксы, тесты эмуляции, план кастомного провайдера - [iis-host-migration-2026-05-19](sources/iis-host-migration-2026-05-19.md) — IIS Host Migration Session 2026-05-19 chronology - [iis-migration-to-ruvds-2026-05-23](sources/iis-migration-to-ruvds-2026-05-23.md) — IIS migration to RUVDS — session 2026-05-23/24 (SSH/scp pivot, 25 SNI bindings, partial DNS cutover) - [nas-recovery-session-2026-05-18](sources/nas-recovery-session-2026-05-18.md) — NAS Recovery Session 2026-05-18/19 chronology diff --git a/.wiki/log.md b/.wiki/log.md index 6542ec3..cccd96a 100644 --- a/.wiki/log.md +++ b/.wiki/log.md @@ -139,3 +139,5 @@ Append-only log of wiki operations (ingests, promotions, lints, migrations). ## [2026-08-18] ingest | NEW concepts/openapi-generator-3-1-spec-gotchas.md — из F&F openapi-client sched (2026-08-18): генерация Python-клиента из 3.1-спеки openapi-generator 7.24.0. Гочи: (1) ответы `{}` в спеке + wrapped-тело ({task/run/schedule:…}) → pydantic ValidationError, фикс — реальные схемы ответов, обход raw-транспорт + by_alias=True; (2) `const:true` → строковый enum ('true') ломает boolean; (3) oneOf+discriminator → actual_instance=None, контент только через raw JSON; Java 11+ обязателен (системная 8 падает), Windows excluded-порты 8090/8091 (EACCES), консоль cp1251 без →/«». Полные находки F-1..F-5: sched/.agents/inbox репорт 19:15Z; пример sched/examples/admin-client-python (24/24). index.md updated. ## [2026-08-18] ingest | NEW concepts/sched-admin-client-openapi.md — F&F раунд openapi-claim sched (по предписанию таски): Python-клиент одной командой (openapi-generator 7.24.0 из спеки verdaccio 0.1.2), сьют 24/24 + smoke 19/19 против published daemon 0.3.4 (:8127), вердикт «claim подтверждён с оговорками» (8 операций требуют raw-обхода). Код sched/examples/admin-client-python (e89e868), репорт — sched инбокс 19:15Z, находки F-1..F-5 (спеку не чинил). Таска [sched-admin-client-openapi] 🟢. Гочи генерации — concepts/openapi-generator-3-1-spec-gotchas.md. index.md updated. ## [2026-08-18] ingest | UPDATE concepts/openapi-generator-3-1-spec-gotchas.md + concepts/sched-admin-client-openapi.md — round 2 ретест (0.2.0/daemon 0.3.5): все 5 находок F-1..F-5 закрыты, raw_ops.py удалён, 11/11 ранее-сырых операций typed-only, сьют 24/24 + smoke 19/19 (коммит sched d658ff0, репорт sched инбокс 22:55Z). Новые грабли в окружение: CLI спавнит java из PATH а не JAVA_HOME; wrapped-ответы в components.responses → InlineObjectN; info.version не бьётся с версией пакета. index.md hooks обновлены. + +## [2026-08-22] ingest | NEW concepts/omniroute-combo-deepseek-web-tuning.md + sources/omniroute-session-2026-08-22.md — сессия настройки web-комбо omniroute (deepseek-v4-flash/pro-web). Корни вылетов агента: (1) system_message override режет скилы pi, (2) tool_filter_regex ^(bash|computer)$ режет 337/339 тулов, (3) search-модель генерит DEEP_SEARCH-мусор + «Link reading unavailable», (4) quality validation режет стрим на type:error, (5) 503 chat_admission_busy = capacity веб-чата. Фиксы применены: system_message="", regex расширен (базовые+mcp__*), flash think-search→think, maxRetries 2→4, retryDelayMs→4000. Эмуляция tool-calling проверена тестами — исправна. План кастомного провайдера (вытащить executor+translator, без quality validation, persistSession). index.md updated (+2). diff --git a/.wiki/sources/omniroute-session-2026-08-22.md b/.wiki/sources/omniroute-session-2026-08-22.md new file mode 100644 index 0000000..b70c6d3 --- /dev/null +++ b/.wiki/sources/omniroute-session-2026-08-22.md @@ -0,0 +1,42 @@ +--- +title: OmniRoute web-комбо — хронология сессии 2026-08-22 +type: source +tags: [omniroute, deepseek-web, session-trace] +ingested: 2026-08-22 +raw_path: ../raw/omniroute-session-2026-08-22.md +updated: 2026-08-22 +--- + +# OmniRoute web-комбо — хронология сессии 2026-08-22 + +Сессия настройки omniroute-комбо `deepseek-v4-flash-web` / `deepseek-v4-pro-web` (провайдер deepseek-web). Полный вывод в диалоге pi 2026-08-22; здесь — ключевые точки. + +## Контекст + +- pi использует omniroute (localhost:20128) как LLM-провайдера, модель `deepseek-v4-flash-web`. +- Веб-чат DeepSeek (chat.deepseek.com) не имеет нативного function calling — omniroute эмулирует через ``-контракт. +- Симптомы: модель «не видит скилы», агент «вылетает» на вызове тулов, `Upstream response failed quality validation: streaming upstream error`, `503 chat_admission_busy`. + +## Ход + +1. **MCP-тулы omniroute не работают** из pi-сессии (`Unknown Mcp-Session-Id`) — перешли на REST `http://127.0.0.1:20128/api/*`. +2. **Собрали картину**: 2 комбо, round-robin, 3 аккаунта deepseek-web (megan/yulia/vitya), qwen-web (test=error, DNS), deepseek API + tokenrouter (test=active, но API-доступ «за скобками»). +3. **Метрики** показали дисбаланс: pro-web 81% успешности, yulia 64%/40s, vitya 50%/42s (last=error), megan 90–100%. +4. **Найден корень №1**: `system_message` комбо переопределяет системный промпт pi → скилы вырезаются. Убран (`""`). +5. **Найден корень №2**: `tool_filter_regex: ^(bash|computer)$` режет 337 из 339 тулов. Расширен до базовых + `mcp__[a-z0-9_]+`. +6. **Найден корень №3**: search-модель (`think-search`) генерит DEEP_SEARCH-мусор и «Link reading unavailable» при URL. Модель в flash-комбо заменена на `deepseek-v4-flash-think`. +7. **Тесты эмуляции** (1 тул, 25 тулов, stream=true/false) — всё возвращает корректные tool_calls. Вывод: эмуляция исправна; «read("...") текстом» = reasoning_content. +8. **503 chat_admission_busy** — capacity веб-чата DeepSeek. maxRetries 2→4, retryDelayMs 1500→4000. +9. **Идея**: кастомный провайдер на базе вытащенного кода omniroute (executor + translator), без quality validation, persistSession, несколько web-провайдеров отдельными комбо. Обсуждено, не реализовано. + +## Итоговое состояние комбо + +Оба (`deepseek-v4-flash-web`, `deepseek-v4-pro-web`): +- `system_message`: `""` +- `tool_filter_regex`: `^(bash|read|write|edit|grep|glob|list|describe_image|mcp__[a-z0-9_]+)$` +- `config.maxRetries`: 4, `config.retryDelayMs`: 4000 +- flash: модель `deepseek-v4-flash-think` (search убран); pro: `deepseek-v4-pro` (без search и так) + +## Ссылки + +- [[omniroute-combo-deepseek-web-tuning]] — сводный концепт