Commit Graph
3 Commits
Author SHA1 Message Date
Alex CubeandClaude Opus 5 52de3b91eb Живучесть: сокет умирает честно, сторож поднимает браузер сам
Три вещи, и первая - настоящая дыра, а не удобство.

1. Смерть вкладки посреди запроса вешала сервис насмерть. У Session не было
   ни обработчика close, ни таймаута на вызов: закрылась вкладка в момент
   ожидания - обещание не разрешалось НИКОГДА. Запрос висел, очередь за ним
   стояла, сервис при этом выглядел живым и молчал. Теперь close отклоняет
   всё висящее, у каждого вызова протокола потолок 60 с, у подключения 10 с,
   а мёртвый сокет отказывает сразу, а не копит вызовы.

2. ask() повторяет запрос один раз, если вкладка пропала посреди работы.
   Повтор безопасен именно из-за правки первого сообщения: вопрос не
   добавляется к чату, а заменяет его содержимое, поэтому дважды он
   не задастся.

3. Сторож: раз в 30 с проверяет браузер и вкладку и поднимает, не дожидаясь
   вопроса. Раньше восстановление жило внутри запроса, и клиент платил за него
   15-60 секундами своего времени. Ходит через ТУ ЖЕ очередь, что и запросы,
   иначе полез бы в браузер, пока DeepSeek дописывает ответ. Пропускает свой
   черёд, если запрос уже идёт. При неудаче отсрочка удваивается до 300 с:
   обычная причина (профиль открыт другим окном без отладочного порта) сама
   не лечится, и долбиться каждые полминуты значит плодить процессы.
   Выключается ключом watchdog в config.json.

Добавлен GET /api/state - дешёвый снимок для индикаторов: браузер, готовность,
занятость, длина очереди, секунды текущего запроса, последняя ошибка и время
последней проверки. Вкладку не трогает, спрашивать можно хоть раз в секунду.
ВАЖНО для будущего окна с индикаторами: снимок обновляет сторож, поэтому он
устаревает на срок до watchdogSec - смотреть на поле checked, а не только
на ready.

Проверено вживую: сервис поднялся, /api/state отдал ready; браузер убит дважды
- в логе "сторож: Браузер не отвечает, поднимаю...", checked идёт каждые 30 с,
состояние возвращается в ready.

НЕ проверено вживую: восстановление после смерти вкладки ПОСРЕДИ запроса
(пункты 1 и 2). Код компилируется, разбор формата проходит, но подгадать
момент не пробовал.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 14:52:13 +03:00
Alex CubeandClaude Opus 5 8c52cf101c Самодостаточность: движок браузера переехал внутрь, DeepShim больше не нужен
Раньше сервис был обёрткой: каждый запрос спавнил ollama_orchestro/ask.mjs
дочерним процессом, гонял вопрос и ответ через временные файлы и читал
чужой config.json ради профиля браузера. Работать это могло только рядом
с установленным DeepShim.

Теперь всё своё. browser.mjs — перенесённый из ask.mjs движок: CDP-сессия,
помощники страницы со всем, что удалось выяснить про разметку DeepSeek,
отправка с подтверждением, ожидание ответа по состоянию кнопки, работа
с чатами. Пульт, разбор патчей и git остались в DeepShim, сюда не поехали.

Побочно ушли дочерний процесс на каждый запрос и временные файлы: вопрос
и ответ теперь просто переменные. Файл на диске остался только для картинки —
<input type="file"> иначе не наполнить.

Свои настройки вместо чужих: browserExe, profileDir и cdpPort в config.json,
рядом config.local.json для путей конкретной машины (в репозиторий не идёт).
Свой chats.json, тоже не в репозитории: это рабочее состояние, оно
переписывается при каждой смене чата. Образец — chats.example.json.

Добавлен GET /api/probe: что видно во вкладке прямо сейчас.

ВАЖНО: профиль браузера должен быть отдельный. Перед каждым вопросом сайдбар
подчищается от всего, чего нет в своём chats.json, поэтому две программы
на одном профиле удаляют чаты друг друга. Проверено вживую, описано в README.

Проверки: node test.mjs; сквозной прогон с нуля — свой чат заведён сам,
ответ верный; пять правок в одном чате, на шестом запросе новый чат, старый
удалён, сайдбар не растёт.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 13:09:41 +03:00
Alex CubeandClaude Opus 5 f5cf061fcc DeepSeek, притворяющийся Ollama
У веб-версии DeepSeek нет API: ни ключа, ни эндпойнта, только вкладка
в браузере. Этот сервис держит такую вкладку и отдаёт наружу протокол
Ollama, поэтому любая программа, которая уже умеет ходить в Ollama,
подключается к DeepSeek сменой одного адреса.

  GET  /api/tags        три "модели" по числу режимов чата;
                        503, пока браузер с чатом не поднят
  GET  /api/version
  POST /api/chat        images в сообщении уводят в чат со зрением
  POST /api/generate
  POST /api/embeddings  501: веб-чат векторов не отдаёт

Внутри — ollama_orchestro/ask.mjs дочерним процессом: он ничего не
экспортирует и выполняется при импорте, это программа командной строки.
Браузер поднимается напрямую из Node, а не через browser-launch.ps1 из
DeepShim: тот рассчитан на человека за консолью и на занятом профиле
спрашивает Read-Host, а у сервиса некому отвечать. Флаги окна оттуда
перенесены: у неактивного окна DeepSeek не дорисовывает блоки кода.

Чего нет: настоящего потока (формат соблюдается, но ответ приходит
целиком), temperature и num_predict, эмбеддингов, параллельных запросов —
вкладка одна, запросы идут очередью по одному.

Сервис слушает все адреса и ходит в DeepSeek под вашим логином. Только
доверенная сеть; сузить до этого компьютера — host в config.json.

Проверка перевода формата без браузера: node test.mjs

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 12:49:03 +03:00