y83 code / журнал

Журнал релизов 0.8: часть 3 из 9

Полная ветка 0.8 из журнала проекта. Записи идут от свежих к старым, текст взят из CHANGELOG.md без правок — это тот же журнал, что читают разработчик и агент.

записей в ветке
251
приложение
185
бэкенд
59
архив сборок
7
период
19 августа 2026 — 24 октября 2026
страниц
3 из 9

журнал

Релизы ветки 0.8

Здесь записи 61–90 из 251: релизы приложения и бэкенда плюс записи архива сборок — каждая запись со своим набором правок.

0.8.148

13 октября 2026

Changed

  • Раздача окружения переезжает на opencode 2.0.27 (установщик rev 5). В манифесте agent.y83.ru теперь opencode=2.0.27 (был 1.18.31), codex 0.162.1, backend свежей сборки и маркер установщика manager=5. Установщик rev 5 сам сеет OPENCODE_PASSWORD в servers.json и перезапускает живой opencode, если тот не отвечает на /api/info: без этого устройство, обновляющееся с v1, поднимало v2 со случайным паролем, и весь прокси бэкенда получал 401 до ручного перезапуска. Обновление на устройстве — Updates → Environment updater; APK — Updates → Install.
  • Команды в ленте opencode — одной рамкой, как в Codex. Карточка команды больше не раскрывается сама по завершении (раскрыта, только пока команда бежит), вложенные фоны surfaceContainerHigh/surface убраны вместе с лишними отступами, а кнопка Copy под карточкой удалена.
  • Выбор модели в opencode — полноэкранным окном, как «Model» в Codex: фильтр моделей, группы по провайдеру, галочка выбранной и секция уровней reasoning (вместо нижнего шита).
  • Меню сессии opencode: новая секция «Инструменты» — окна «Git и диффы» (/api/vcs/status|diff|branch) и «Терминалы» (/api/shell, /api/pty, запуск команды и вывод); в секции «Ход» появилась «Сжать контекст» (POST /api/session/:id/compact).

Fixed

  • Бесплатные zen-модели в Codex-чате снова отвечают. Free-tier гейт opencode.ai сверяет не User-Agent и не TLS-отпечаток, а маркер типа в id сессии: живой клиент (opencode v2.0.27) всегда шлёт ses_ + 9 hex + ffe + 14 символов, а наш генератор ставил случайные hex — гейт отвечал 403 FreeTierError на весь запрос. Теперь internal/sessionid повторяет клиента (убывающая метка времени + маркер ffe; у msg_ — 001), поэтому и лейны роутера, и локальные сессии zen-прокси проходят гейт.
  • Картинки-вложения в ленте opencode показываются превью, а не строкой имени файла: байты читает бэкенд (как картинки Codex), тап открывает просмотрщик.

0.8.147

13 октября 2026

Changed

  • Бабл ответа в opencode-чате повторяет Codex. Убрана цветная полоса слева, длинный текст прокручивается внутри бабла (как в Codex, с ограничением под предел тач-событий Android) — кнопки «Развернуть»/«Свернуть» больше нет. В подвале появилось время хода (под последним текстовым блоком) и кнопка «Код · N» — копирует все блоки кода ответа (как Code · N в Codex).
  • Живое рассуждение агента ведёт себя как в Codex: раскрыто, пока идёт ход, следует за текстом и сворачивается по завершении. Строки app_chat_expand / app_chat_collapse удалены из ресурсов.

0.8.146

13 октября 2026

Fixed

  • MCP в чате opencode снова подключается. Ручки v2 (connect, disconnect, а также interrupt, wait и revert/commit) не объявляют тело запроса, а клиент отправлял POST вообще без него — OkHttp на это падает сам с «method POST must have a request body», и кнопка «Подключить» только писала красную строку в окне. Теперь POST/PUT/PATCH всегда уходят с пустым JSON-объектом: вместе с MCP починились Стоп и «revert commit».
  • Новый тред opencode снова получает имя. Сессия создавалась с title = "", а пустая строка для v2 — это уже заданный заголовок: авто-имя по первому сообщению (Проверка связи) не подставлялось никогда. Теперь сессия создаётся без заголовка, а до появления авто-имени в списке и шапке виден фолбэк «Новый чат». Заодно имя подтягивается в открытый чат сразу после первого хода, не дожидаясь перезахода.
  • Тред создаётся в каталоге проекта. POST /api/session не получал локацию, поэтому v2 заводил сессию там, где запущен opencode ($HOME) — и агент работал не в проекте. Локация уезжает в теле запроса.

Changed

  • Страница «Навыки» оформлена как у Codex. Терминальная шапка opencode@skills, секции по источнику (встроенные / глобальные / проектные), компактные карточки вместо трёхстрочных описаний с обрезанными путями. Содержимое навыка открывается markdown-рендерером чата (SKILL.md как документ, а не сырой текст), кнопка «Прикрепить» осталась внизу окна, текст по-прежнему можно выделять и копировать.

backend 0.8.242

13 октября 2026бэкенд

Fixed

  • y83-imagegen доехал до раздач скиллов. Скилл генерации картинок завели 1 октября, но он не попал ни в вайтлист серверной раздачи (remoteSkills — скиллы для агента на Ubuntu-сервере), ни в набор skills.tar.gz для устройств (scripts/publish-skills.sh): на удалённом агенте оставался только bundled .system/imagegen, который не знает про mcp__y83__image_generate. Теперь в ~/.codex/skills на сервере едут y83-webai, y83-websearch, y83-remote и y83-imagegen, а на раздаче лежат шесть скиллов. Чтобы скилл больше не терялся молча, publish-skills.sh печатает WARN, если в репе есть скилл, которого нет ни в раздаче, ни в dev-only списке.

Changed

  • skills.tar.gz собирается детерминированно (tar --sort=name с обнулёнными mtime и owner). Раньше skills= в манифесте менялся от прогона к прогону при том же содержимом, и устройства перекачивали архив на каждой выкладке.
  • MCP-сервер y83 снова провижнится установщиком (rev 8). На обновившемся устройстве скиллы приезжали, но в ~/.codex/config.toml не было секции [mcp_servers.y83]: её сеял только старый установщик (под легаси-именем mcp_servers.y83ws), а приложение пишет лишь тумблеры (enabled/disabled_tools). Экран Skills показывал у каждого скилла «сервер y83 не настроен в config.toml», а у агента не было веб-поиска, веб-ИИ, браузера и генерации картинок. Установщик rev 8 добавляет каноническую секцию (url = "http://127.0.0.1:4100/mcp/codex"), переименовывает легаси y83ws → y83 вместе с подсекциями, чинит устаревший url и перезапускает codex, чтобы app-server перечитал конфиг.
  • Установщик больше не пугает ложным WARN про opencode. После перезапуска opencode v2 первый старт (206 МБ бинарь + миграция opencode.db) занимает больше 30 с, поэтому ожидание /api/info увеличено до 120 с, а в WARN теперь печатается диагностика api/info=<код> pid=<pid> body=<тело> log=<хвост>: 401 — пароль не принят, 000 — процесс не слушает порт, 500 — процесс жив, но падает внутри (причина видна в body).
  • Установка скиллов больше не падает на префиксе ./. Проверка архива требовала имена записей вида ./y83-X/SKILL.md, а сборка tar на другой машине может писать их без префикса — при том что хэш архива уже сверен с манифестом. Из-за этого на устройстве установка обрывалась с «skills: в архиве нет SKILL.md». Теперь принимаются оба варианта, а в сообщении об ошибке видно размер архива и первые пути.
  • Установщик больше не считает поломкой живой opencode с 500 на /api/info. У v2 эта ручка на части устройств падает при работающих сессиях и моделях, а установщик по ней судил о сервисе и звал перезапуск. Теперь готовность проверяется по нескольким ручкам (/api/info, /api/session, /api/model): любая 200 под паролем из servers.json — сервис жив (в логе версия «жив (без /api/info)»), перезапуск только при 401 на всех ручках или тишине. Заодно в диагностике починен free (свободное место в МБ).

backend 0.8.238

13 октября 2026бэкенд

Fixed

  • Цены моделей снова приходят в статистике. GET /api/v1/stats собирал каталог через opencode models --verbose, а в opencode 2.0.27 такого флага нет, поэтому секция models приезжала пустой и в чате Codex пропала стоимость хода в $. Теперь каталог читается из API самой opencode (GET /api/model) — у каждой модели там cost ($/1M токенов). Тарифы в этой таблице базовые, поэтому зависящие от времени суток скидки (off-peak у DeepSeek) в подписи ~$ не отражаются: это оценка, а не счёт.

backend 0.8.237

13 октября 2026бэкенд

Added

  • Каталог моделей отдаёт уровни reasoning. GET /api/v1/models теперь возвращает variants — список уровней модели в порядке opencode v2 (только id, без settings). Набор свой у каждой модели: где-то none/minimal, где-то xhigh, поэтому шкала не фиксированная, а приходит от сервера. Это тот же variant, который приложение и так отправляет в POST /api/session/:id/model, так что выбор уровня не понадобилось нового эндпоинта. Раньше список обрезался по ID/Name/Limit/Capabilities, и в шапке чата нечего было показать.

backend 0.8.235

12 октября 2026бэкенд

Changed

  • В ответе правки одна ссылка на исходник. source_url остаётся входным параметром image_edit и style_refs, но больше не повторяется в ответе: и в payload, и в санитизированной записи реестра ссылка на исходник теперь одна — source.image_url, копия в uploads/ самого media API, которую и нужно подавать в source_url следующего шага. Заодно выровнена дедупликация: одна и та же картинка, скачанная по разным URL, с теми же параметрами снова схлопывается в один job (хеш запроса и так включает image_sha256, а source_url его больше не разводит).

backend 0.8.234

12 октября 2026бэкенд

Added

  • MCP image_quota: видно остаток лимита media API. Новый read-only тул читает GET {image_url}/quota и отдаёт limit, used, remaining, resets_in_seconds — то же минутное окно (100 запросов/мин на токен), которое считает rate limiter API. Ничего не генерирует и не заводит запись в реестре jobs, поэтому запас можно спросить перед пачкой картинок; у остальных image-тулов исчерпанное окно по-прежнему приходит кодом quota.

backend 0.8.233

12 октября 2026бэкенд

Added

  • Правка по публичному URL. image_edit и style_refs принимают source_url: backend скачивает картинку сам (≤8 МБ, только публичные хосты — loopback, приватные, link-local и ULA-адреса отклоняются, редиректы перепроверяются) и дальше ведёт её тем же путём, что локальный файл, поэтому mask_region считается по реальным размерам скачанного кадра. Из статуса теперь известен source.image_url/source.mask_url — этот URL подставляется в source_url следующего шага, и цепочка правок идёт без файлов на диске.

Changed

  • Статус job читается на v2 с long-poll вместо legacy /api/v1/jobs. Клиент больше не ходит во внутренний v1-статус: GET {image_url}/generate/{id} отдаёт operation, progress_text, queue_position, эхо параметров (params), source (ссылки на исходник и маску), style_refs и concept_sliders без картинок, poll_after_ms, attempts, started_at и is_favorite — всё это теперь в payload image_status, image_edit и image_generate. Ожидание использует ?wait= (до 10 с на запрос, не выходя за дедлайн): живая правка 1253 заняла 6 обращений вместо ~27 опросов каждые 2 секунды. dead_letter считается терминальным состоянием, а fallback на /api/v2/jobs/{id} при отмене убран.

backend 0.8.232

12 октября 2026бэкенд

Fixed

  • image_status больше не теряет операцию, исходник и референсы. Живой ответ media API несёт только id/статус/картинки, поэтому image_status и REST GET /api/v1/image-jobs/{id} (кнопка Status refresh на карточке) возвращали payload без operation, source_id, style_refs и concept_sliders — после refresh карточка показывала меньше, чем сразу после генерации. Теперь в payload подмешиваются поля из записи реестра (request_json) тем же кодом, что и в пути восстановления.

backend 0.8.231

12 октября 2026бэкенд

Added

  • Стиль по референсу и слайдеры понятий. image_generate и image_edit принимают style_refs (до 12 локальных картинок: source_id/source_path, recipe, strength 0–1.2) и concept_sliders (до 8: name, value −6…+6, полюса). Референс уходит в API base64-копией (URL для референсов API не принимает), recipe выбирает, что именно брать из картинки — свет, палитру, материал, фон, композицию (32 значения из openapi.yaml, по умолчанию balanced). Оба поля только для krea2-turbo. Ответ показывает style_refs_applied/style_refs[] (recipe, strength, image_sha256, размер) и concept_sliders_applied/concept_sliders[], а хеш запроса включает референсы и слайдеры — два разных стиля не схлопываются в один job.

Changed

  • Лимит тела запроса поднят с 1 МиБ до 32 МиБ. Ограничение жило в nginx перед media.y83.ru (client_max_body_size 1m в vhost media.y83.ru), сам движок на 192.168.1.64 принимал тело в 32 МБ и раньше — проверено живыми пробниками. Бюджет клиента теперь 26 МиБ (64 КиБ зарезервировано под JSON-обёртку), и его делят исходник, маска и все референсы: обычный PNG 1024×1024 уходит байт в байт, а JPEG-пережатие (92 → 48 без смены размеров) осталось страховкой для негабаритных картинок. Ошибка 413 по-прежнему классифицируется как invalid_request, но в тексте теперь 32 МиБ.

0.8.145

13 октября 2026

Fixed

  • Лента opencode больше не перевёрнута. Сервер v2 отдаёт страницу сообщений «новые → старые», а лента читает список хронологически — поэтому мой промпт оказывался ниже ответа агента, а самые свежие ходы прижимались к верху. Порядок нормализуется один раз на входе в репозиторий (data/repo/ChatOrder.kt), и та же инварианта чинит цифры, которые считались по списку: $ хода и % кэша берут последний ход (а не первый), уведомление — последний текст, session.diff — последний ответ агента. Легаси-кэш в y83-chat.db лечится на чтении, миграция не нужна. order=asc у opencode не используем: он возвращает самую старую страницу, а не свежую историю.

Added

  • Экран «Навыки» в чате opencode (меню сессии → Сведения → Навыки): каталог скиллов локации из GET /api/skill (10 штук у нас, вместе с текстом механики), тап открывает текст скилла, «Прикрепить» кладёт навык к следующему сообщению — чипом в композере и полем skills[] в промпте. Тумблеров нет: выключать скиллы API v2 не умеет.
  • Экран MCP в чате opencode заменил прежнюю заглушку (жёстко вписанные ai_ask/web_search/web_fetch): теперь это настоящий список серверов из GET /api/mcp со статусом (подключён, подключается, выключен, ошибка, нужна авторизация), причиной падения и кнопкой подключить/отключить (POST …/experimental/mcp/{server}/{connect,disconnect}). Переключение действует до перезапуска opencode — об этом сказано в окне.

0.8.144

12 октября 2026

Added

  • Лента opencode рендерит ответы как чат Codex. Текст агента, вывод инструментов и содержимое read/write переехали с Markwon на общий Compose-рендерер (ui/markdown/render): в ответах снова подсвечивается код, таблицы рисуются таблицами, !alt — миниатюрой (тап открывает просмотрщик), а текст выделяется долгим тапом. Ссылки сохранили прежний роутинг: путь .md — просмотр файла, остальное — браузер.
  • У ответа агента в opencode появилось меню действий (кнопка ⋮ рядом с копированием): «Копировать всё / текст / код (N) / таблицы (CSV)» — пункты показываются, только когда в ответе есть что взять отдельно, — и действия сессии «Откатить до этого сообщения» и «Форк отсюда» (с прежними подтверждениями; форк принимает before и открывает новую сессию).
  • Меню сессии opencode стало окном с секциями (как «Thread settings» в чате Codex): сверху чипы состояния — модель, уровень, заполнение контекста (с 80% краснеет), — дальше карточки «Ход» (откат, возврат отката, форк), «Сессия» (переименование с текущим именем, удаление) и «Сведения» (статистика, MCP). Пунктов про personality, service tier, handoff и review нет: в opencode v2 таких сущностей нет. Подписи строк и диалогов (переименование, откат, удаление, форк) переехали из кода в res/values* — меню и подтверждения теперь на русском в RU-локали.

Changed

  • Шапка чата opencode — как в чате Codex. Заголовок на градиентной вуали с hairline снизу, под ним строка «модель · уровень reasoning», справа меню. Выбор модели ушёл из нижней панели (там остались вложения, роль и Send): в кодексе он тоже наверху, и больше не спорит с полем ввода за место. Уровень reasoning переключается там же — в окне модели первой секцией «Рассуждение»; набор чипов берётся из variants модели, метр усилия считается по позиции уровня в этом списке. Строка статуса (связь, ветка) показывается только когда есть что сказать: постоянное «online» в шапке только шумело.
  • Расход контекста — строкой над лентой, а не полоской. Слева занятое окно и процент с порогами 70/90, справа доля кэша чтения; тап открывает разбивку токенов, стоимости нет. Считается по последнему ответу агента (input + кэш), а не по сумме за сессию: сумма за 50 сообщений давала 8.7M при окне 262k, то есть больше 3000%.
  • Имя модели и уровень разъехались. Раньше подпись модели в шапке брала variant (displayModelName), и при variant: max чип показывал «max» вместо имени модели. Теперь имя — из каталога, уровень — отдельным чипом.
  • Поле ввода opencode — как в чате Codex. Вложения переехали чипами внутрь карточки (отдельной строкой над полем они висели в стороне от того, к чему относятся) и показывают имя с размером. Пустое поле компактное (12dp), с первой буквой верхний отступ растёт до 28dp под счётчик символов, две строки вместо трёх, текст и плейсхолдер — стилем агента. Enter отправляет (многострочное — Shift+Enter), после отправки клавиатура прячется и фокус с поля снимается. В нижнем ряду кнопка вложений стала меню композера (Widgets 40dp, primary), роль получила иконку и подпись стилем события, Stop встал перед Send — обе 40dp, поэтому высота ряда не прыгает при появлении кнопки. Тень карточки — ровно 8dp, как в кодексе.
  • Уровень reasoning видно всегда, когда модель его имеет. Раньше чип появлялся только если у сессии уже стоял variant, а на живых тредах его почти никогда не было (variant: default или пусто) — выбрать уровень было негде. Теперь невыбранный уровень показывается как «Авто» приглушённым цветом с пустым метром, а в окне модели это первый чип секции «Рассуждение»: выбор снимает variant, и провайдер берёт свой дефолт.

Fixed

  • Чип уровня reasoning не мог появиться в принципе. Приложение берёт каталог у бэкенда (GET /api/v1/models), где variants — список строк, а разбор ждал объектную форму {id, settings} сырого /api/model opencode. Список всегда выходил пустым, и условие показа чипа не выполнялось никогда.
  • Чат переставал падать в «Could not connect». В opencode v2 state.error у части инструмента — объект {type, message}, а не строка; одно поле роняло разбор всего ответа истории, и экран уходил в состояние ошибки вместе с выбором модели. Плюс выбор модели и агента теперь реально применяются: в v2 они задаются на сессии (POST /api/session/:id/model и /agent), а не в теле промпта.

Removed

  • Мёртвый код v1 из чата. Вопросы агента (в v2 их заменили формы), части step-start/step-finish и индикатор шага в шапке, подсистема тасков и карточек сабагентов вместе с фильтром SSE по их сессиям (инструмента task в v2 нет), подсветка кода (палитра принималась и молча игнорировалась), а также функции без единого вызова. Модели и effort выбираются на сессии, как в v2, и ничего не подстраховывается «старым форматом».

Added

  • Карточка генерации показывает референсы и слайдеры. В деталях image_generate/image_edit появились строки «style refs» (recipe и strength по каждому референсу) и «sliders» (blur -3.5), а поля style_refs/concept_sliders переживают компактификацию ingress-проекции, поэтому карточка не теряет их при перезаходе в тред. Строка «style refs» показывает ещё и откуда взят референс: 816 или 817#2 для своей генерации, имя файла для локальной картинки, плюс размер (1.2 MB); референс без recipe больше не пропадает из деталей.
  • Ссылки, картинки и HTML в тексте открываются тапом. В ответах агента и в планах голые https://…, а также абсолютные и ~/ пути к картинкам и .html (в бэктиках или обычным текстом) стали кликабельными: URL и HTML — во встроенном браузере, картинка — в полноэкранном просмотрщике, прочий путь копируется в буфер. !alt рисуется миниатюрой в бабле, а тап открывает просмотрщик. Раньше тап работал только у markdown-ссылок, а путь .md молча копировался в буфер.
  • Справка «Что умеет Krea» на карточке генерации. В хабе Tools (медиа → генерация изображений) появилась кнопка, открывающая полноэкранную памятку по Krea 2 Turbo: разделы рассказывают, что можно нарисовать и как просить, чем правится готовая картинка (img2img/inpaint/outpaint, источник по номеру, файлу или ссылке), что дают референсы, слайдеры, сид и LoRA, что переживает таймаут и перезапуск бэкенда, и какие у сервиса ограничения (маска — прямоугольники, лимит 100 запросов в минуту). Окно-инструкция получило разделы с заголовками помимо нумерованных шагов.

Fixed

  • Токен-бар: $ вернулся, сумма токенов Σ убрана. Над лентой в обоих чатах — один общий бар (ui/components/ChatUsageBar): слева занятый контекст и процент, справа стоимость хода в $, затем доля кэша (цена строго левее кэша, как было до 0.8.134). Промежуточная сумма токенов (Σ …) убрана — её добавили по ошибке, в баре нужна стоимость, а не «сколько всего нажгли». В чате opencode стоимость берётся у сервера v2 (cost ответа агента), поэтому off-peak тариф, скажем, DeepSeek учитывается сам, и цена точная — без тильды ($0.0076); в чате Codex цена считается по каталогу, это оценка, и она помечена тильдой (~$0.0025). Нулевая цена — это $0, а не пустое место: бесплатный ход тоже полезно видеть.
  • В чате opencode под ответами агента больше нет строки in/out/ctx/cache. Она дублировала токен-бар; разбивка по токенам по-прежнему открывается тапом по бару.
  • Итог хода в ленте opencode — как в Codex. Под последним ответом агента появилась строка-разделитель «Готово · 1m 42s · 3 инстр. · 2 изм. · 48.2K ток.»: ход в работе итога не имеет, ход без работы и токенов строку не рисует. Граница хода — промпт пользователя, отдельного события хода в v2 нет. Компакт контекста рисуется такой же строкой («Контекст сжат») вместо прежней плашки на secondaryContainer.

Added

  • История opencode-чата больше не пропадает. Лента открывается из локального кэша (y83-chat.db, миграция 10→11, таблицы opencode_*): вход в чат мгновенный, без сети видна последняя история, а ход, который шёл до перезапуска приложения, доигрывается из журнала событий — не дожидаясь ответа сервера. Канон — серверный список сообщений, он перекрывает кэш, как только приходит; дубли при реконнекте SSE отсекает ключ (sessionId, eventId); очередь промптов, вопрос-формы и запросы прав хранятся последним снапшотом, поэтому карточка вопроса остаётся отвечаемой и после перезахода. Журнал ограничен (2000 кадров на сессию), сессии, к которым не обращались месяц, убираются; всё, что уже стало каноном, из журнала вычищается.
  • Шапка opencode одинаковая у всех сессий. Строка «online · master» под моделью рисовалась только там, где у сессии есть git-ветка, и часть чатов была на строку выше остальных. Теперь строка появляется лишь при обрыве связи («reconnecting…»/«offline») — как в чате Codex, а ветки в шапке нет.

Changed

  • Пакет чата opencode переехал: ui/chat → ui/opencode. Общие хелперы разметки (Markdown, подсветка JSON) ушли в ui/components, а транспорт (opencode-API, SSE, каталог моделей бэкенда) — в data/repo/OpencodeChatRepository: ViewModel больше не ходит в сеть напрямую.

Added

  • Полоса статуса в opencode-чате — как в Codex. Над полем ввода вместо плашки «Агент работает» теперь служебная строка в стиле чата Codex: в ходу — живой этап («запускаю npm test», «читаю /path», «правлю /a/b.kt», «думаю…», «пишу ответ…»), таймер хода и тонкая полоса прогресса; в простое — «готов». Этап собирается из живых частей ответа, поэтому видно, чем агент занят сейчас, а не только «работает». Пока агент ждёт ответа на вопрос-форму или одобрения прав, полоса говорит именно это. Обрыв связи по-прежнему показывает шапка — статус не дублируется в двух местах.
  • Очередью промптов opencode можно управлять. Элементы, которые ещё не доехали до агента (session.inbox.*), рисуются полосками как очередь в Codex: «Сейчас» переводит элемент в steer — промпт вклинивается в текущий ход, не дожидаясь его конца; «В поле» возвращает текст в поле ввода (элемент при этом снимается); «Отменить» убирает его из очереди. Текст элемента v2 править не умеет — PATCH /inbox/{id} меняет только режим доставки, поэтому вместо «Изменить» из Codex здесь «В поле».

Fixed

  • В токен-баре больше нет второго знака $. Иконка валюты и подпись цены дублировали друг друга ($ ~$0.178); иконка убрана, знак остался в тексте. Строка для скринридера не изменилась.
  • Оценка хода в чате Codex учитывает тариф по размеру контекста. Каталог отдаёт ступени (tier.type=context): например, у gpt-6-luna выше 272k контекста цена вдвое выше. Раньше всегда брался базовый тариф, и ~$ занижал ход на большом контексте. Кэш (чтение и запись по своим ставкам) учитывался и раньше; тарифов по времени суток нет ни в каталоге opencode, ни в models.dev, поэтому off-peak в подписи ~$ не появляется — это по-прежнему оценка.

backend 0.8.230

12 октября 2026бэкенд

Added

  • MCP image_edit: правка готовых картинок. Krea 2 Turbo получил img2img, inpaint по прямоугольникам и outpaint: источник — своя прошлая генерация (source_id, source_index) или локальный файл (source_path), область задаётся в пикселях исходника (mask_region, до 8 прямоугольников), кадр расширяется через anypaint_padding, сила перерисовки — denoise (0.85 инпейнт / 1.0 аутпейнт / 0.45 img2img; 1.0 — реальная замена объекта). Картинка уходит в API base64-копией, поэтому правка не зависит от доступности собственного публичного адреса, а в реестре и в ответе агента лежит санитизированная запись без байтов (image_sha256, размеры, operation); хеш запроса включает хеш самого исходника, поэтому два разных источника не схлопываются в один job.
  • У генерации появились параметры Krea. image_generate принимает seed, krea_lora/krea_lora_2 с силами, krea_4step и post_upscale (2x/4x), а model — ещё и flux2-klein-4b (быстрый draft, steps 1–8, без LoRA и upscale).

Fixed

  • Правка больше не упирается в лимит тела. nginx перед media.y83.ru отклоняет тело запроса больше 1 МБ (HTML 413), а обычный PNG-исходник 1024×1024 весит ~1.3 МБ и в base64 не проходил. Теперь backend сам пережимает крупный исходник в JPEG по лестнице качества (92 → 48), сохраняя пиксельные размеры: mask_region остаётся в координатах исходника. В ответе видны image_format, image_bytes, image_compressed, image_quality и alpha_flattened, а ошибка 413 классифицируется как invalid_request, а не как загадочный unknown.
  • image_cancel снова отменяет задачу. Клиент обращался к DELETE /api/v2/jobs/{id}, который отвечает 405; документированный маршрут API v2 — DELETE /api/v2/generate/{id} (легаси /jobs/{id} остался фолбэком). Кнопка Cancel в карточке генерации снова работает.
  • Статус честно сообщает операцию. image_generate, image_edit, image_status и image_jobs отдают operation (text2img/img2img/inpaint/outpaint/inpaint_outpaint) и mode, а если v1-представление статуса исчезнет, клиент переходит на GET /api/v2/generate/{id}.

0.8.143

12 октября 2026

Added

  • Карточка Image edit. Результат правки рисует та же галерея с отдельным заголовком; в Info видны операция, источник и его размер, формат и вес копии (и признак дожатия), прямоугольники перерисовки, padding, denoise, LoRA, seed и upscale. Габариты превью берутся из результата (outpaint меняет кадр), а не из аргументов запроса, и плейсхолдеры-мокапы остаются только у новой генерации.

0.8.142

12 октября 2026

Fixed

  • Экран выбора приложений больше не выглядит пустым первые секунды: пока PackageManager отдаёт метки, иконки и время обновления, в шапке горит «загрузка приложений…», а в списке — лоадер с подсказкой. Раньше это время экран показывал «выбрано 0 / 0 приложений» и пустой список — читалось как «ничего не работает».
  • Повторный заход в список обновляет его молча: уже загруженные приложения остаются на экране, лоадер не мигает, параллельный проход не запускается.

0.8.141

12 октября 2026

Fixed

  • Лента больше не вырывает позицию чтения, пока идёт активный ход. Решение «следовать за хвостом или держать позицию» выводилось из переходов состояния прокрутки и из собственной пометки «это наш скролл»: пометка снималась только на остановке, а остановки после программного скролла могло не быть вовсе — пометка залипала, ваш жест принимался за программный, и лента на каждом изменении контента (несколько раз в секунду) возвращалась к хвосту. Замер без единого касания экрана: флаг «ушли от хвоста» мигал каждые 2–5 секунд (SCROLL_AWAY → SCROLL_BACK), а окно ленты ходило 300 ↔ 500 элементов. Теперь намерение меняет только палец (DragInteraction): программная прокрутка — наша и внутренняя компоновка ленты — не может ни выключить, ни включить следование.
  • Уход от хвоста замечается сразу, пока палец ещё на ленте, а не по остановке скролла: короткий жест или программный скролл больше не оставляют ленту в режиме «следуем», из-за которого она дёргалась туда-сюда и возвращалась к месту, с которого вы начали скролить (в таймлайне — SCROLL_FOLLOW touch-away).

0.8.140

12 октября 2026

Fixed

  • Лента больше не дёргается, пока идёт активный ход. Раньше прокруткой управляли два независимых механизма (следование за хвостом и анкер позиции), и оба переезжали сразу после того, как вы начинали читать, — на каждом изменении ленты (несколько раз в секунду) вылетала программная прокрутка, а позицию могло «перекинуть» далеко от того места, где вы читали. Теперь у прокрутки один хозяин: во время жеста лента не двигается вообще, а решение «следовать за хвостом или держать позицию» принимается на остановке и только после этого (см. docs/tech/codex-chat-perf.md).
  • Пока вы читаете, приложение не прокручивает ленту вообще: позицию держит Compose по ключу элемента, на котором вы остановились, а новые карточки в хвосте докручиваются у него же. Программная прокрутка при чтении отменяла ваш жест и заказывала пере-мер раскладки — отсюда были рывки «дёргается и возвращается к месту, с которого я начал скролить» (замер на живом ходе: до 188 коррекций позиции на 5–18 изменений ленты). Разъезд позиции, если он всё же случится, теперь виден в диагностике SCROLL_DRIFT, а лента не дёргается.
  • Карточка плана, которая живёт в полоске плана, больше не занимает место в ленте: раньше она держала пустой слот с отступом, и высота ленты менялась в момент старта и конца хода.

0.8.139

12 октября 2026

Added

  • Применение режима и набора приложений к живому туннелю теперь подтверждается сервисом: :vpn после пересбора TUN шлёт com.y83.ws.vpn.POLICY_APPLIED, экран показывает плашку «Режим применён: весь трафик / только выбранные приложения (N)», а в статус-карточке на время пересбора горит строка «применяются настройки…» — переключатель All ↔ Per-app больше не выглядит неработающим.
  • Меню списка приложений: тумблер «Показывать системные» (по умолчанию выключен — вместо 563 приложений показываются пользовательские), сортировка «по имени / по недавним» (время обновления из PackageManager, без новых разрешений) и «Снять все (N)» с подтверждением.
  • Пустой поиск объясняет, что системные приложения скрыты, и сколько их нашлось.

Changed

  • Экран выбора приложений перешёл на общий вертикальный ритм приложения (FirstSectionTopPadding, SectionHeaderContentSpacing, sectionHeaderSlot): поиск больше не прижат к терминальной шапке (12dp), между поиском и чипами — 12dp, шаг секций — как на остальных экранах.
  • Настройки экрана (системные приложения, порядок списка) помнятся в prefs vpn_apps_show_system и vpn_apps_sort.
  • Массовые действия в меню считают показанное: в фильтре «Выбранные» они работают по выбранным строкам, а не по всему списку.
  • Причины реконнекта в статус-карточке переводятся (нет сети, сменилась сеть, туннель не отвечает, …) — раньше строка была английской в любой локали.
  • Сравнение применённой политики в сервисе идёт по множествам, а не по спискам: тот же набор в другом порядке больше не вызывает лишний пересбор TUN.
  • Плашки экрана VPN показываются через TypedNoticeBar (в том числе «ссылка скопирована») — в общем стиле уведомлений приложения.

0.8.138

12 октября 2026

Changed

  • Экран VPN → «По приложениям» переверстан: сверху поиск и чипы «Все N» / «Выбранные M», массовые действия переехали в меню («Выбрать все видимые», «Снять у видимых»). Выбранные подняты отдельной секцией // selected, в строке — бирюзовый бордер и явная галочка вместо мелкой метки; пустой список и пустой поиск объясняются текстом, а не пустым экраном.
  • Массовые действия работают по видимым строкам: «Выбрать» добавляет к набору (при активном поиске выбранное вне фильтра больше не теряется), «Снять» снимает только видимое.
  • Режим и набор приложений применяются к уже поднятому туннелю сами, с дебаунсом ~600 мс: пересобирается только TUN, hysteria2 и время сессии не трогаются — Disconnect/Connect для этого больше не нужен.
  • Раздел VPN переведён на RU/EN: подписи, кнопки, поля формы сервера, диалоги, пустые состояния, счётчики (<plurals>) и текст уведомления живут в strings_vpn.xml; терминальные токены (y83@vpn/…, // server, connected) остались латиницей как язык терминала.
  • Мост: новая команда vpn_apps — режим, число и список выбранных пакетов.

Fixed

  • Выбранные приложения, которых больше нет на устройстве, висели в счётчике и не снимались из списка — теперь набор чистится при загрузке с сообщением «Убрано удалённых приложений: N».
  • В режиме «По приложениям» с пустым набором кнопка «Подключить» больше не уводит весь трафик в туннель: подключение заблокировано с подсказкой, а живой туннель при снятии последней галочки остаётся на прежнем наборе.
  • Иконки приложений грузятся одним проходом в фоне (раньше — по одной на каждый пакет, список «перетряхивался» на 500+ приложениях).

backend 0.8.227

12 октября 2026бэкенд

Fixed

  • Публикация в GitLab больше не падает на could not read Username for 'http://192.168.1.68': origin собирается из адреса в настройках (baseUrl), а не из http_url_to_repo ответа API. Инстанс может отдавать внутренний хост (external_url в gitlab.rb), к которому не привязан токен — credential.helper скоупится на baseUrl, и push уходил в запрос логина. Если origin уже стоял на таком адресе, он переставляется на адрес из настроек.
  • Чужой origin: если проект по пути из origin отвечает нашему GitLab (запрос по токену находит проект), origin признаётся нашим — расхождение хостов больше не требует галочки «заменить origin».
  • Ссылки в списке проектов (httpUrl/webUrl) тоже собираются на адресе из настроек: тап по проекту открывает https://gitlab.y83.ru/…, а не внутренний http://192.168.1.68/…, недоступный извне домашней сети.

0.8.137

12 октября 2026

Fixed

  • Инструкция по токену GitLab описывала старое меню (Preferences → Access tokens → Add new token). Теперь шаги под GitLab 17.10+/18: аватар → Edit profile → Access → Personal access tokens → Generate token → Legacy token, scope api, срок 90 дней. Добавлены две подсказки: нужен именно legacy-токен (fine-grained не даёт полного API) и путь для GitLab 16 и старше. Поле называется «Токен доступа (legacy PAT, scope api)».

Changed

  • Кнопка «Открыть страницу токенов» ведёт на форму с предзаполненными name=y83-ws и scopes=api: GitLab открывает создание токена с готовыми полями.
  • Окно-инструкция (Tools и GitLab) переверстано: номер шага в моно-колонке 20dp на одной оси с текстом, приглушённые подсказки под шагами по той же левой оси, блок «Важно» — карточка с полем 16dp, кнопка в подвале с иконкой перехода, единые отступы 16dp по сетке 4dp.

0.8.136

12 октября 2026

Changed

  • Экран «Интеграции» (Tools) переоформлен: терминальная шапка y83@tools с мета-строкой «интеграций 5 · токенов N», карточки разложены по секциям — «поиск и код» (GitHub, AgentSearch), «медиа» (картинки), «документация» (Context7) и «git» (карточка-переход на экран GitLab).
  • Кнопка «Сохранить» переехала в закреплённый подвал и активна только при несохранённых правках; итог сохранения показывается строкой статуса под шапкой, а не всплывающей плашкой снизу. Выход с введённым, но не сохранённым токеном спрашивает: сохранить или выйти (системная кнопка «назад» — тоже).
  • Экран Tools полностью локализован (RU/EN, strings_tools.xml): раньше все подписи были английским текстом прямо в коде.

Added

  • Кнопка «i» у каждого блока (GitHub, AgentSearch, картинки, Context7, GitLab): окно-инструкция с нумерованными шагами «как получить токен», предупреждением и кнопкой «Открыть страницу токенов» — ссылка уходит во встроенный браузер.
  • Экран GitLab: инструкция по токену (кнопка «i» в шапке и в карточке подключения; путь {baseUrl}/-/user_settings/personal_access_tokens), «глаз» на поле токена, мета-строка шапки (адрес · токен · проектов), тап по строке проекта открывает его в браузере, отдельная иконка копирует ссылку.

0.8.135

12 октября 2026

Added

  • GitLab (gitlab.y83.ru): экран в хабе (Tools → GitLab) — токен, проверка, список проектов и публикация репозитория. origin ставится сам: создаётся проект (по умолчанию группа y83, private), добавляется remote и делается первый push с upstream. Имя проекта вводит человек (обязательное поле, предзаполнено именем папки), группа — из конфига, перед кнопкой видно превью «будет создан y83/<имя> · private».
  • Публикация понимает уже прописанный remote: если origin ведёт в наш GitLab (https, ssh://, scp-форма, .git), проект берётся по URL — origin не меняется (adopted), поля имени/группы игнорируются. Если этот путь занят непустым проектом, публикация отказывает (code: project_exists) и показывает отчёт — ветка, коммиты, видимость, активность и ссылка — с галочкой «пушить в существующий проект» (только для человека); пустой проект переиспользуется без подтверждения. Чужой origin (не наш GitLab) по-прежнему требует галочку «заменить origin», из агента такие подтверждения недоступны.
  • Токен GitLab живёт только на бэкенде (~/.y83-ws/gitlab.json, 0600) и никому не отдаётся: приложение и агент видят лишь «токен задан». В git-команды он подставляется URL-scoped credential.helper: локально через env, на Ubuntu-сервере эфемерно по stdin (файл удаляется в той же ssh-команде, в ps секрета нет).
  • MCP-инструменты gitlab_status, gitlab_projects, gitlab_publish, gitlab_git: агент умеет работать с ветками и проектами, но не видит токен. Политика запрещает из агента force-push, --mirror/--all, удаление веток, push в защищённые ветки (по умолчанию master), управление remotes и запись в глобальный git config.
  • Скилл y83-gitlab и docs/tech/gitlab.md — как агенту работать с GitLab и почему токен не выдаётся.

0.8.134

12 октября 2026

Fixed

  • Markdown-парсер больше не зависает на «битой» таблице: строка вида | a | b | без строки-разделителя — обычный абзац, а не начало блока. Раньше такая строка не сдвигала позицию разбора, и чат замирал на сыром тексте (разбор идёт под NonCancellable, отменить его было нечем).
  • Вложенный контент в списках и цитатах больше не исчезает: код, таблица, подсписок и абзац после пустой строки внутри пункта, а также любые блоки внутри цитаты и callout рисуются общим диспетчером блоков (render/BlockDispatch.kt) — раньше всё, кроме абзацев, молча пропадало.
  • Цитата и callout с отступом внутри пункта списка (- пункт и > цитата) снова блоки: распознавание шло по строке вместе с отступом, поэтому > оставался видимым текстом пункта, а строки цитаты склеивались в одну.
  • Курсив и жирный разбираются по правилам flanking: 2 3 4 остаётся как есть, a*b*c — курсив, а snake_case_name — литерал. Работают _курсив_, __жирный__, экранирование (\*) и код-спаны из нескольких бэктиков.
  • Markdown-файл в просмотрщике выделяется и копируется, как обычный текст.

Changed

  • Токен-бар Codex-чата читается слева направо как «сколько занято»: слева 60.8K/950.0K и процент заполнения контекста (красится по порогам 70/90), справа — сумма хода и доля кэша. Процент заполнения больше не скрывается на узких экранах (screenWidthDp < 400): на телефоне 520 dpi (≈362 dp) его из-за этого не было видно вовсе.
  • У токен-бара и полосы лимитов модели убраны полоски прогресса: остались только цифры, проценты и кнопка Switch от 80% — тонкие индикаторы больше не дублируют уже написанные числа, а процент заполнения красится по порогам 70/90.
  • Поле ввода композера по умолчанию стало высотой в две строки вместо одной: короткое сообщение видно целиком, а под длинный текст поле растёт как раньше (до пяти строк, в развёрнутом виде — до тысячи).
  • Дамп текстового потока модели (выключен по умолчанию): ROUTER_DUMP_STREAM_DIR или файл-флаг ~/.y83-ws/router-dump/stream-enabled пишет чанки апстрима и отданный клиенту текст (stream-<slot>-<kind>.jsonl) — по нему видно, пришёл ли пробел от модели или потерялся по дороге (см. docs/tech/dev-workflow.md).

0.8.133

12 октября 2026

Fixed

  • zen-модели больше не показывают кэш 0%: zen-прокси переносит prompt_tokens_details → input_tokens_details и completion_tokens_details → output_tokens_details (проба space-bunny-free вернула 183 кэшированных из 444). Честными стали доля кэша в баре, «cached input» в шитах и стоимость хода — раньше она считалась по полной цене.
  • Форма id кэш-сессии: free-tier гейт Zen пускает только ses_ + 12 строчных hex + 14 [0-9A-Za-z] (28-символьный id старой формы получал 403 «free tier can only be used from within OpenCode»). Теперь и лейны роутера, и локальные сессии прокси выдаёт один генератор (internal/sessionid), а прокси пробрасывает входящий заголовок только правильной формы.

Changed

  • У zen-провайдера появился лейн на разговор: роутер ставит x-opencode-session из общего стора, прокси пробрасывает его наверх, поэтому ротация кэш-сессии на zen-треде отвечает lanes=1 вместо noop.
  • Сторож кэша судит и ротирует только провайдеров с лейном (promptCache от бэкенда: opencode.ai напрямую и встроенный zen-прокси). У моделей без лейна пункт «Reset cache session» скрыт, а на экране Cache watch появилась строка о границах сторожа — ложных баннеров и noop-предупреждений больше нет.
  • Учёт ротаций: одноразовая миграция убрала события lanes == 0 вместе со счётчиками по моделям и дням (52 пустых авто-сброса zen/space-bunny-free).

0.8.132

12 октября 2026

Changed

  • Единый вертикальный ритм заголовков секций на 38 экранах и шитах: полосу заголовка держит сам компонент (heightIn(min = 48.dp)), первый заголовок садится на FirstSectionTopPadding (16dp), шаг контейнера — SectionHeaderContentSpacing (8dp), разрыв перед не первым заголовком — только sectionHeaderSlot(hasPreviousContent = true). Вертикальные паддинги из вызовов убраны (раньше отступы расползались 4/6/8/10/12/16dp), остались горизонтальные инсеты контейнеров.
  • Ворота ui-spacing (tools/ui_spacing.py + self-test): вертикальный паддинг в modifier вызова SectionHeader — нарушение, осознанное исключение — комментарий // ui-spacing: allow.

Fixed

  • Мягкий перенос в markdown больше не рвёт текст и разметку: строки параграфа склеиваются пробелом (BlockParser), пункт списка с продолжением переразбирается целиком (ListParser) — жирный и ` код на переносе сохраняют разметку, а в ленте видна вся фраза, а не первая строка. Покрыто тестами MarkdownParserTest` («soft wrapped list item keeps bold…», «soft wrapped paragraph joins lines with a space»).

Added

  • Человеческая документация: docs/about/ — 34 страницы «что умеет приложение и как этим пользоваться», docs/codex/ — 10 страниц про чат с агентом (обе с индексами), плюс техническая карта docs/project/ (архитектура, Codex-чат, 36 инструментов хаба — по файлу на инструмент). Навигация между слоями — в docs/README.md.
  • Тулы документации: tools/doc-unwrap.py (мягкие переносы в человеческих доках) и tools/doc-sentence-check.py (предложения-отсылки) — ручные, в ворота не входят.

0.8.131

10 октября 2026

Changed

  • Внутренний рефакторинг без изменений в поведении: SessionRepository больше не читает App.appContext() — префы и клиент opencode приходят конструктором (OpenCodeApi открыт для подмены подклассом в тесте). Заодно один клиент на репозиторий вместо нового на каждый вызов.
  • Удалены мёртвый ProjectRepository и неиспользуемый OpenCodeApi.projects(): продакшн-вызовов у них не было (проекты грузит ProjectsViewModel через DAO и opencode-API напрямую).
  • ViewModel'и Search, Prompts, Vision, Providers, Scheduler, CodexSessionResets, WebAiChat не читают локатор App.backendRepos() внутри класса: репозиторий приходит параметром, а читает локатор только фабрика — единственное место композиции для своего экрана.
  • Шов данных покрыт тестами: OpenCodeReposSeamTest (офлайн-фолбэк списка сессий, кэш числа сообщений, флаг архива) и JVM-фейк FakeSharedPreferences — без Android и без сети.
  • Поведение ViewModel'ей впервые проверяется на фейковых репозиториях: MainDispatcherRule (тестовый Main для viewModelScope) и PromptsViewModelBehaviorTest (загрузка, отказ бэкенда, валидация до отправки, оптимистичный счётчик использований), CodexSessionResetsViewModelBehaviorTest (сводка, пагинация с дедупликацией, «Clear history»). Для этого в тесты добавлен kotlinx-coroutines-test.
  • Лог-зеркало (FileLog) больше не пишет по относительному пути: если внешний каталог недоступен (getExternalStoragePublicDirectory вернул пусто), зеркало отключается — раньше в этом случае создавался y83ws/log.txt в рабочем каталоге процесса (замечено юнит-тестом).
  • Хаб инструментов и Home Settings заговорили на выбранном языке: 36 пунктов каталога (названия, описания, подписи тайлов главной), заголовки секций, мета-строка шапки и подписи доступности ушли в res/values* (RU/EN); бренды и тех-термины (MCP, Codex, WebAI, API, VPN, Termux, Vision, Prompts) остаются латиницей, английский текст не изменился. Тексты пунктов больше не могут быть захардкожены — поля каталога стали ресурсными id. Гейт i18n теперь проверяет и <plurals>: имена, непустые формы, обязательная other и паритет RU↔EN (мета-строка хаба — «N инструментов · M разделов»).
  • Сабагенты больше не делят кэш с родителем: Codex кладёт в prompt_cache_key id сессии (родительский тред), а свой тред — только в client_metadata.thread_id, поэтому родитель и все его сабагенты уходили в один лейн шлюза и вытесняли префиксы друг у друга (замер 11.10.2026: кэш 99–100% → 3–18% на контекстах 150–275k токенов, ~9M входных токенов по полной цене за десять минут). Роутер ключует лейн по треду клиента и пишет router subagent lane в лог бэкенда. Сторож кэша ведёт счёт на каждый тред, лечит фоновые сабагенты авто-ротацией (уведомление + учёт) и не «сбрасывает» себя на пустой ротации: ответ rotated=0 теперь виден как cache rotate noop, а не как успех.

0.8.130

10 октября 2026

Changed

  • Внутренний рефакторинг без изменений в поведении: BackendApi больше не создаётся в ui/ нигде (rg "BackendApi\(" app/src/main/java/com/y83/ws/ui — пусто). Доменные репозитории холдера App.backendRepos(baseUrl) пополнились: SqliteRepository (схема, страницы, правки, произвольный SQL), SearchRepository, PromptsRepository, VisionRepository, EnvRepository (версии, сборка APK/бэкенда, выкладка, логи, обновление), SchedulerRepository, SessionRotationRepository (ротации prompt-кэша), WebAiChatRepository (веб-ИИ чаты, группы, шаблоны, стрим), ImageJobsRepository (медиа-задачи) и ServiceControlRepository (точечный start/stop сервиса).
  • Переведены ViewModel'и Search, Prompts, Vision, Updates, Scheduler, CodexSessionResets, SqliteBrowser, Databases, WebAiChat и codex-расширения (CodexViewModel, CodexCacheActions, CodexModelActions, CodexPaths, CodexRecovery, CodexAttachmentActions, CodexImageActions); вложения Codex-чата пишутся через FsRepository. Шов данных покрыт тестом SearchRepositorySeamTest (ViewModel собирается на фейковом репозитории и не ходит в сеть).

0.8.129

10 октября 2026

Changed

  • Внутренний рефакторинг без изменений в поведении: BackendApi больше не создаётся в экранах, которые ходят на адрес конкретного агента. Репозитории одного ws-backend собраны в холдер data/repo/BackendRepos (один HTTP-клиент на адрес, домены создаются лениво), а локатор App.backendRepos(baseUrl) кэширует холдер по адресу и заменил пять прежних функций (policyRepository, toolsRepository, healthRepository, fsRepository, apiProvidersRepository).
  • FsRepository расширен до полного набора файловых операций (home, stat, statfs, du, search, mkdir, move, copy, delete, readFile, writeFile, writeFileBytes, upload, downloadTo), и LocalFsSource (файловый менеджер, вьюер, планы Codex) работает через него. Добавлены WebAiRepository (аккаунты веб-ИИ, провайдеры, настройки webget) и StatsRepository; затронуты ui/files, WebAiScreen, WebAiAccountFormScreen, WebgetSettingsSheet, ChatTokenUi, ChatViewModel, StatsScreen, CodexPlansScreen, CodexImageCards.
  • Кэш холдеров по адресу покрыт юнит-тестом BackendReposTest.