app 0.8.185
Fixed
- MCP-профиль в чужом проекте показывал инструменты y83-ws. Экран MCP брал
mcpServerStatusу ещё не загруженного треда: app-server возвращал пустой список, а UI оставлял статусы предыдущего треда — подписьcore, а tools те же 65+3. Теперь экран сначала поднимает тред (thread/resume) и только потом читает его инструменты. Хаб (без треда) показывает глобальный профиль, а не последний открытый тред. - Context7 снова подключается. Локальный прокси
/mcp/context7освобождён от локального токена (ключ Context7 подставляет бэкенд), иначе Codex получал 401 и терял три инструмента.
[Unreleased]
Fixed
- После «Разрешить» бар больше не висит в «waiting for your answer». Ответ на карточку разрешения снимал её, но оставлял
requires_action: статус ждал следующего запроса модели, то есть всю генерацию картинки. Теперь ожидание считается только по открытой карточке, ответ (и старт инструмента, который CLI разрешил сам) переводит ход вrunning, а имя MCP-инструмента в баре читается какy83 · image_generate. - Сгенерированная картинка видна сразу, без раскрытия «Работы». Вызовы
image_generate/image_edit/image_status/image_cancelбольше не входят в свёрнутую группу инструментов: у них отдельная карточка с галереей и просмотрщиком. - Тело скилла больше не выглядит сообщением человека. Claude пишет его в транскрипт как
user-запись сturnCompanion/sourceToolUseID; история отбрасывает такие companion-записи (и не считает их ходом), при этомisMeta-записи с настоящим промптом рядом с<system-reminder>остаются. - У работающей карточки инструмента идут секунды. Время бралось только из
tool_progress, а MCP-вызовы (в том числеimage_generate) heartbeat не шлют — карточка молчала всю генерацию. Теперь незавершённый вызов тикает от метки старта, итог фиксируется по завершении, а heartbeat по-прежнему авторитетнее локального счётчика.
Changed
- Смена режима, модели и уровня в Claude-чате читается плашкой. Раньше это была тонкая строка с
Infoи сырым значением CLI (Mode: acceptEdits). Теперь компактная плашка с иконкой настройки, переходом «было → стало» и временем;bypassподсвечен предупреждением. Чип режима в композере получил тот же вид: бордер, иконка, короткая подпись, у режима не по умолчанию — акцентный бордер. - Подтверждения remote-exec знают свой тред. Приложение берёт
approvalIdиз результатаremote_execи привязывает заявку к конкретному Codex-треду: в уведомлении и карточке видно имя треда, тап ведёт ровно в него (включая фоновый тред через восстановление туннеля), а в диалоге сначала идут заявки открытого треда. Уведомления группируются по треду, два треда на одном сервере больше не сливаются в одно. Если привязки ещё нет (opencode-сессия, холодный старт) — «тред не определён» и тап в Approvals. Звук только на первое появление очереди, дальше тихие обновления и summary. - Меньше лишних подтверждений на серверах. Классификатор разбирает shell: безопасные
;,&&, пайпы,2>/dev/nullи read-only циклы выполняются сразу. Для изменяющих команд появился явный grant «разрешить сервер на 10 минут» с отзывом; секреты, SSH-ключи, firewall и критические операции всё равно требуют отдельного подтверждения.
Added
- Режим
native: Codex и Claude Code от собственной подписки. Экран «Аккаунты агентов» (хаб → AI & Agents) даёт по одному переключателюy83 | nativeна тип агента. ВnativeCLI ходит напрямую по подписке (ChatGPT для Codex, Claude Pro/Max для Claude Code): роутер не подставляет ни адрес, ни токен, а изconfig.tomlснимаютсяmodel_provider,model_catalog_jsonи секцииy83_router. Политики, MCPy83и context7 остаются. Вход выполняет сам CLI (codex login --device-auth,claude auth login): токены подписки наш код не читает и не проксирует. Пока режимnative, а входа нет, ход не отправляется — чат показывает «вход не выполнен» вместо невнятного отказа, и тихого отката на роутер нет. Пикер моделей следует режиму: Codex берётmodel/listу app-server, Claude — нативный список CLI. Стоимость хода в native не считается: подписка не даёт цены за токен. - Протокол на уровне модели: GPT Luna, Grok и Claude Haiku в одном провайдере. Шлюз
opencode.aiсмешивает пути:gpt-6-luna,gpt-5.6-luna,grok-4.6/4.7иmuse-spark-*contributorпринимают только/responses,claude-haiku-5-5иminimax-m2.7— только Anthropic/messages. Раньше у провайдера был одинprotocol, и такие модели падали сModelProtocolUnsupported; теперь у каждой модели есть своё полеprotocol(пусто — наследовать провайдерский). Роутер пробует протоколы по очереди, но повторяет запрос только когда апстрим отверг именно формат (ModelProtocolUnsupported, 404/405) и пока клиенту не отдан ни байт: на429/5xxи таймауты повтора нет, иначе квота и гейт жгли бы лишние запросы.403повторяется только с теломModelProtocolUnsupported— шлюз помечает так неподдерживаемый формат;RegionErrorиFreeTierErrorс тем же кодом остаются окончательным отказом. Принятый протокол запоминается в модели, ручной выбор не перетирается. Дляmessagesдобавлен полный транспорт в обратную сторону (chat↔Messages API, включая SSE) и заголовкиx-api-key+anthropic-version. Ответ конвертируется по фактически принятому протоколу, поэтому клиент всегда получает свой формат (choicesили SSE Responses), даже когда автоподбор ушёл на другой путь. - Молчаливая потеря сообщений при конверсии. Внутри роутера один и тот же список живёт как
[]any(после JSON) и как[]map[string]any(собранныйresponsesToChat); конвертер в Anthropic понимал только первый и отправлял в/messagesзапрос без сообщений («at least one message is required»). - Проверка доступности моделей провайдера. Кнопка «Проверить доступность» в шторке действий и листе моделей прогоняет каждую модель одним запросом на 1 токен (
POST /api/v1/providers/{id}/models/probe, конкурентность 4, кэш час) и пишет в сторprobe: работает ли, каким протоколом, а при отказе — причину (region,privacy,no upstream,protocol,auth). Бейдж виден в карточке модели и в диалоге discover; «all» больше не включает заведомо мёртвые модели. Так видно, чтоgemini-4-argonшлюз не проксирует ни одним протоколом,mimo-v2.5-proотсутствует в апстриме, аiceman-contributor-freeотвечает 503. - Claude Code: итог хода — «Изменено файлов». Под последним ответом появилась карточка со списком тронутых файлов и счётчиками
+a −r; раскрывается в список, тап по файлу показывает его diff. Отдельного события «итоговый diff хода» CLI не присылает, поэтому карточка собирается из уже пришедших карточек Write/Edit/MultiEdit: файл считается один раз, повторы складываются по строкам, упавший инструмент не считается. Граница — последнее сообщение человека, а не вся история. - Claude Code: очередь сообщений и палитра
/…. Набранное во время хода больше не уходит вторым ходом поверх первого: сообщение встаёт в локальную очередь над композером (правка тапом по тексту, «Отменить», «следующее») и отправляется само, когда CLI закрыл ход (turn_finished, а неstatus=idle— между ходами CLI ещё дописывает транскрипт). Предел — 20 сообщений, отказ виден в поле ошибки. «Отправить» появляется только когда ход уже не идёт: прерывать работающий ради очереди нельзя. В композере — палитра команд: список приходит изinit.slash_commandsсамого CLI (встроенные команды, скиллы, плагины), раньше мост отдавал только счётчик. Команды, работающие лишь в терминале, помечены — в headless-режиме они отвечают «unavailable». - Claude Code: MCP-серверы и окно MCP. Агент получил настоящий MCP:
~/.claude.json→mcpServers.y83с локальным токеном (профильcore, в этом репозитории —devчерез--mcp-config), провижн идемпотентен и переживает ротацию токена. В меню чата — секцияtoolsс пунктом «MCP servers» («подключено/всего»), окноclaude@mcpпоказывает живые статусы из самого CLI (mcp_status): транспорт, версия, инструменты и текст ошибки, с Reconnect для упавших и тумблером вкл/выкл (действует до перезапуска процесса — CLI не пишет его в конфиг).initтеперь не теряетmcp_servers: сводка видна ещё до открытия окна. Заголовки серверов (configсX-Y83-Token) мост вырезает и в приложение не отдаёт. - Claude Code: действия сессии в меню чата. Секция
sessionокна «Chat settings» доделана до паритета с меню треда Codex: New session, Rename session, Session info, Keep screen on, Stop turn и Delete session. Переименование меняет имя в шапке сразу (POST …/title), Info показывает id, модель, режим и статистику транскрипта, удаление стирает сессию вместе с транскриптом и возвращает на список. Rename/Info/Delete гаснут, пока сессии нет в транскрипте, Delete — ещё и во время хода; мета секции показываетworking/waiting. - Claude Code: меню шапки вместо иконок-действий. Справа в шапке чата теперь одна кнопка
⋮— она открывает окно «Chat settings» в стиле меню треда Codex: модель, уровень рассуждений, режим разрешений, токены, затраты и список сессий. Уровни переехали в отдельное окноclaude@reasoning(чип уровня в шапке ведёт туда же), режимы — вclaude@mode, токены — вclaude@tokensс разбивкой хода и сумм сессии. Stop и история ушли из шапки (Stop остался в композере), поэтому во время хода шапка не меняется, а длинное имя модели больше не ломает чип уровня по буквам. - Claude Code: токен-бар и история затрат. Над лентой — тот же бар, что в Codex: занятый контекст последнего запроса / окно модели,
context %, цена хода по реестру тарифов и доля кэша; тап открывает окно затрат треда со ходами по дням. Ходы пишутся вturn_costs(scopeclaude) и видны в общем экране «Затраты»; старые сессии бэкфиллятся из транскрипта. Роутер теперь прокидываетcache_read_input_tokensиcache_creation_input_tokensв Messages API (без этого CLI видел только input/output и кэш терялся). - Claude Code: лента как в Codex — шаги, карточки инструментов, хвост. Работа агента (размышления + инструменты) собирается в сворачиваемые шаги «шаг N» / «шаги N–M» с временем и счётчиком; шаг живой — раскрыт, после завершения сворачивается и открывается тапом. Карточки инструментов теперь по виду инструмента: Bash (команда + stdout/stderr, длительность), Read (файл), Write/Edit/MultiEdit (путь,
+N/−M, unified diff изstructuredPatch), TodoWrite (чек-лист), Grep/Glob/WebFetch/WebSearch/Task и MCP — компактной строкой. Мост отдаёт компактнуюmetaрезультата (stdout,stderr,structuredPatch,content, безoriginalFile), длительность инструмента поtsсобытий иthinkingDurationMs. Лента переведена наreverseLayoutс общим авторитетом прокрутки Codex: автоследование за хвостом, пилюля «к последнему» со счётчиком новых ответов/ошибок, вставка в середине не рвёт позицию чтения. - Claude Code: разрешение над композером. Карточка Allow/Deny висит между статус-баром и полем ввода и видна при любой прокрутке; в ленте остаётся компактная строка решения. В снапшот добавлен
seq, и SSE подписывается сLast-Event-ID, поэтому история не дублируется реплеем кольца. - Claude Code: выбор reasoning effort. CLI принимает
--effort(low…max) и меняет уровень на ходу; мост передаёт его вPOST …/effort, роутер — вreasoning_effort/reasoning.effortс нормализацией по модели. В шапке чата — чипauto/low…maxс метром, в окне модели — секция// reasoning.output_config.effortиз CLI раньше выбрасывался роутером, поэтому уровень не доезжал до провайдера. - Claude Code — третий агент, на наших провайдерах. Официальный CLI Anthropic ставится в Termux как glibc-бинарь (
patchelfна$PREFIX/glibc/lib/ld-linux-aarch64.so.1, без Node и без bun-прослоек) и ходит в роутер через новый Anthropic-совместимыйPOST /codex-router/v1/messages. В приложении — свой чат: лента, размышления, карточки инструментов, разрешения Allow/Deny, выбор модели из каталога провайдеров, режим (manual/acceptEdits/plan/bypass), список сессий с продолжением и счётчики токенов. Мост — Go внутри ws-backend (backend/internal/claude), CLI запускается дочерним процессом. - Claude Code: экран проектов. Карточка агента теперь открывает проекты, как у Codex: папки из транскриптов CLI плюс метки (переименование, «убрать метку»), live-статус «идёт»/«ждёт разрешения», превью последнего вопроса, счётчик сессий и PullToRefresh. Сессии из терминала видны как живые (
~/.claude/sessions), тестовые папки из$TMPDIRскрыты, сводки транскриптов кэшируются. Список сессий проекта получил поиск, группы по датам и удаление транскрипта (идущую сессию удалить нельзя — сначала Stop). - Claude Code: экран сессий как треды Codex. Карточки с плиткой-глифом, статус-строкой (таймер хода, «ждёт разрешения», «в терминале», «обновлено»), бегущей полосой во время хода, превью последнего вопроса и счётчиком токенов; меню Rename / Info / Stop / Delete. Список живёт: опрос раз в 3 с, пока экран открыт. Переименование пишется в транскрипт CLI (
custom-title), поэтому имя видно и вclaude --resume; окно Info показывает модель, папку, время, ходы и токены. Идущую сессию и сессию, занятую терминалом, удалить нельзя — бэкенд отвечает409. - Claude Code: чат с шапкой и композером как в Codex. Шапка — та же градиентная вуаль: имя сессии, чип модели (окно выбора с поиском и группами по провайдеру; выбор запоминается для новых сессий), «Сессии» и Stop. Над полем — статус-бар (
WorkingBarиз Codex): этап (running: Bash · …,thinking…,waiting for your answer), таймер хода и полоса прогресса. Композер — карточка 20dp/тень 8dp с вложениями-чипами, счётчиком символов, expand/collapse, меню (Attach, Prompts…, Keep screen on, язык диктовки), меню режимов, голосом и Stop/Send по 40dp. Вложения идут путём в~/y83-ws/uploads/— агент читает файл сам, без правок моста.
Fixed
- zen снова работает в Claude-чате. Free-tier гейт opencode.ai требует инструменты ровно
bashиreadв нижнем регистре, а Claude Code присылаетBash/Read: гейт находил их без учёта регистра, но не переименовывал (EqualFoldсчитал имена совпавшими), и апстрим отвечал429 FreeUsageLimitError. Теперь имя приводится к каноническому всегда, а вызовы возвращаются клиенту под его именами. Codex и opencode не страдали — у них имена уже нижним регистром. - Выбор модели в Claude-чате больше не подменяется. Окно брало каталог opencode (
/api/v1/models), где встроенный zen называетсяopencode; роутер такого id не знал и молча подставлял первую модель списка — в шапке одно, исполнялось другое. НовыйGET /api/v1/claude/modelsотдаёт каноничес- кие слаги роутера (zen/…,opencode-go/…,deepseek/…), аaliasModelподменяет только служебныеclaude-*; неизвестная модель —404. - Отказ провайдера в Claude-чате виден и останавливает ход. 429 уходил в тихий ретрай CLI: полоса «работает» крутилась минутами, а причина не показывалась. Теперь
system/api_errorи синтетическийassistantидут в ленту карточкой ошибки, ход завершается, а у CLI остаётся две попытки (CLAUDE_CODE_MAX_RETRIES). Messages-путь роутера лечит засвеченный лейн так же, как Codex: приFreeTierError/FreeUsageLimitлейн меняется и запрос повторяется. - Claude-чат не пишет «no connection» на новой сессии. Флаг связи поднимался только первым SSE-событием: у пустого чата и после обрыва потока шапка врала про обрыв, хотя REST работал. Теперь баннер только для живой сессии без потока,
connectedподнимается успешным ответом бэкенда, а потерянный поток переподключается на следующем ходе. - Отозванная
minimax-m3.1-flash-freeубрана из zen. Апстрим отвечает410 ModelDeprecated; миграцияzen.jsonv4 вычищает её из сохранённого каталога, сид и страховочная цепочка research её больше не берут. - Claude-чат падал при втором тапе по режиму. Служебные строки ленты («Модель: …», «Режим: …») строили id из счётчика, который не увеличивался: два переключения подряд давали один ключ, и
LazyColumnпадал сKey "mode-N" was already used. Теперь id уникальны, счётчик растёт. - Claude-режимы: весь набор CLI и честный bypass. В меню были четыре режима из шести — добавлены
dontAskиauto;bypassPermissionsтеперь работает: процесс стартует с--allow-dangerously-skip-permissions, а включение требует отдельного диалога подтверждения. Отказы CLI (control_response) больше не проглатываются:POST …/modeи/modelотдают502с текстом, чип откатывается к прежнему значению. - Композер Claude: кнопки больше не выглядят одинаково. Меню композера перешло на иконку
Widgets(как в Codex), а чип режима получил свою иконку для каждого значения и меню с заголовком// permission mode— его больше не путают с «выбором агента» (модель живёт в шапке). - Лента opencode-чата открывается с вопросами, а не стеной ответов. Страница в 50 сообщений у opencode — это 49 ответов агента и 0 запросов человека, поэтому чат открывался работой без контекста. Теперь стартовая загрузка идёт вглубь до двух запросов (не больше четырёх страниц), а курсор «показать более раннее» не откатывается при фоновом опросе.
- Расход токенов больше не удваивается.
session.tokens— уже накопленная сумма по сессии, но приложение прибавляло к ней сумму по сообщениям: окно токенов показывало двойной расход. Теперь источник истины — серверная сумма, а сумма по сообщениям осталась фолбэком для старого кэша. - Ошибка провайдера видна в ленте. Ответ с пустым
contentи полемerror(лимит, отказ авторизации) выбрасывался как служебная запись: вопрос человека оставался без ответа и без причины. Теперь такой ответ рисуется блоком с текстом ошибки, а ход считается упавшим. - Кнопка diff под ответом агента работает.
GET /diff?from=принимает только id запроса пользователя, а UI передавал id ответа — сервер отвечал «not a user message». Теперь id переводится на запрос, открывший ход. - Ретрай провайдера показывает попытку и причину.
session.status.retryнесётattempt,messageиnext, но они терялись в парсере. - Аргументы инструмента видны ещё до запуска. Дельты
session.tool.input.deltaотбрасывались, и карточка доcalledоставалась с одним именем. - Шрифт opencode-чата следует настройкам чата, как в Codex. Блоки
read,write,edit, диффы, вывод инструментов, окна терминалов, навыков, MCP, модели и меню сессии рисовались жёстко (bodySmall+Monospace+ 11 sp), поэтому выбор шрифта и размера в настройках на них не действовал. Теперь все они идут черезchatStyle(...): код —ChatTextType.Code, подписи —Meta, — а номера строк диффа масштабируются вместе с кодом. - Экран opencode-чата больше не смешивает языки. Английские хардкоды («How can I help?», «Changed files», «Session tokens», тосты об ошибках и вставке) переехали в
res/values*. - Ответ в opencode-чате больше не задваивается после перезапуска приложения. Если приложение перезапускалось посреди хода, живая копия уже записанной в историю части оставалась в
livePartsпод другимmessageID, и лента дорисовывала её вторым баблом (без подвала с временем и меню). Теперь live-сообщение не добавляется, если такая же часть уже есть в истории — сверка по ключу части, id вызова инструмента и полному тексту. - Карточки рассуждений в opencode-чате больше не «крутятся» все сразу.
session.reasoning.endedприходил без статуса и с проигнорированным текстом, а живые части навсегда оставались стриминговыми: каждая мысль шага показывала спиннер и растущий таймер до конца хода. Теперь конец события фиксирует длительность и сворачивает карточку, а граница шага (step.ended/новыйstep.started) закрывает рассуждение и текст, если событие потерялось при реконнекте. Полоса хода перестала показывать «Thinking»/«Writing» после того, как этап закончился. - Роль сессии переключалась только в одну сторону (plan → build не срабатывал). Кэш экрана (
session) не обновлялся после успешной смены роли, поэтому повторный выбор отсекался проверкой «сервер уже на этой роли»: чип показывал Build, а сессия оставалась в plan. Теперь послеPOST /agentсерверная роль перечитывается и ложится в кэш, а событияsession.agent.selectedсинхронизируют его с другими клиентами. - Во всех проектах opencode-чата был один список сессий. Список запрашивался с
?location[directory]=…, ноGET /api/sessionпонимает только плоский?directory=…и на deepObject фильтр молча игнорирует. Запрос исправлен, плюс клиент дополнительно отбирает сессии по каталогу (защита от старого кэша и версий сервера, которые фильтр не применяют); это же чинит «удалить сессии проекта», которое раньше могло унести чужие. - Каталог сессии снова читается (
location.directory). v2 отдаёт его вложенным, а приложение смотрело плоскоеsession.directoryи получало null — из-за этого подписка SSE, каталоги навыков/MCP и счётчики сессий у проектов работали без каталога. - Архив сессий переехал на сервер (2.1.4). Отметка живёт в
time.archived(PATCH /api/session/{id} {"archived":…}), а не в префах приложения: архив из TUI виден в приложении и наоборот. «Show archived» запрашивает?archived=true, а старые локальные отметки один раз переносятся на сервер при первом запуске.
Changed
- Страница проектов opencode стала живой, как список тредов Codex. Карточка показывает, сколько сессий проекта идёт и сколько ждёт ответа (
GET /api/session/active+ открытые permission/form; опрос раз в 3 с и только при видимом экране), бегущую полосу хода и превью — последнее сообщение пользователя самой свежей сессии. Живые проекты поднимаются наверх, дальше по свежести; в шапке —N sessions · M projects · K live. «~» теперь означает настоящую домашнюю папку Termux, а не workdir агента.
Added
- Команды на удалённых серверах из Codex-чата. MCP-профиль
/mcp/codexполучилremote_servers,remote_exec,remote_exec_statusиremote_job. Серверы берутся из реестра приложения (без паролей), read-only команды выполняются сразу, изменяющие ждут подтверждения в приложении (точная сохранённая команда, TTL 10 минут), длинные уходят в фоновые job с логами и pid на сервере. В/mcp/remoteи opencode инструментов нет.