y83 code / инструмент

Терминал

«Терминал» — интерактивная оболочка внутри приложения. Это не обёртка над Termux-эмулятором, а собственная реализация терминала: свой эмулятор ANSI/VT, свой транспорт (локальный PTY Termux и SSH для удалённых хостов), свой рендерер и свои жесты.

раздел реестра
Инструменты
код
1 474 строк в 5 файлах
документ
03-terminal.md
Раздел: Tools
Идентификатор: terminal · Экран: ui/shellchat/ + ui/terminal/ + terminal/
Снимок: 2026-10-11
Экран вырезан из приложения (15.10.2026): описанная ниже реализация
удалена целиком (terminal/, ui/terminal/, хаб-плитка terminal).
Документ оставлен как история; возврат — только по ТЗ
docs/tech/prompt-terminal-argon.md.

1. Зачем и что это

Два режима работы с выводом:

  • терминальный вид (TerminalPane, ui/terminal/TerminalPane.kt) — полноценный эмулятор с PTY, управлением мышью, tmux, TUI-программами;
  • чат-вид (ui/shellchat/) — тот же вывод, но разобранный на сообщения (ShellChatParser), с полем ввода и лентой: удобно для агента и для длинных логов.

Один и тот же экран умеет переключаться между этими представлениями и работать с несколькими хостами одновременно: активная сессия на экране, остальные живут в фоне.

2. Как попасть

Хаб инструментов → секция Tools → карточка «Терминал» (hub_terminal_title, подпись «Интерактивная оболочка для локальных и удалённых хостов», тайл «Терм.»).

Откуда ещёПуть
Чат агентазапуск команды открывает Screen.ShellOutput
Мостapp_navigate с screen: "terminal"

Маршрут: Screen.kt:123 ("terminal" -> Screen.ShellChat) → MainRouter.kt:528 (ShellChatScreen). Экран вывода команды — Screen.ShellOutput.

3. Экран: элементы и действия

ЭлементЧто делаетГде в коде
Панель терминалаЭмулятор VT: текст, цвета, курсор, выделение мышьюui/terminal/TerminalPane.kt
Слой жестовСвайпы, пинч-зум, колесо мыши, долгий тапui/terminal/TerminalGestureLayer.kt
Панель доп. клавишESC/TAB, фиксируемые CTRL и ALT, цифры, стрелкиui/terminal/ExtraKeysBar.kt
Список целейЛокальный Termux + все удалённые серверы из RoomShellSessionManager.targetList
Поле ввода (чат-вид)Отправка команды в активную сессиюui/shellchat/ShellChatInputBar.kt
Лента (чат-вид)Разобранные блоки выводаui/shellchat/ShellChatFeed.kt, ShellChatRows.kt
Лист настроек чат-видаПараметры отображения выводаui/shellchat/ShellChatSettingsSheet.kt

Экран вывода ShellOutputScreen (Screen.ShellOutput) показывает готовые строки с заголовком — это «только чтение», без ввода.

4. Возможности подробно

Цели и сессии

ShellSessionManager (terminal/ShellSessionManager.kt) держит ConcurrentHashMap сессий и целей. Изначально есть одна цель — ShellTarget.Local (локальный Termux). Дальше список целей пополняется из Room: менеджер стартует подписку на App.remoteServerDao().observeAll() и на каждый сервер заводит свою сессию (applyServers).

Активная цель — activeTargetId: StateFlow<String>, по умолчанию Local.id. Менеджер запускается в App.init(): shellSessions = ShellSessionManager(app); shellSessions.start().

Важная деталь подписки: Room поднимается лениво, поэтому start() ждёт готовности DAO, пробуя до 30 раз с паузой секунда, и только потом коллекционирует — иначе коллектор упал бы на NPE. Если DAO так и не появился, пишется ShellSessions: server list unavailable в лог приложения.

Локальный Termux

TermuxLocalSetup (terminal/TermuxLocalSetup.kt, 249 строк) готовит локальное окружение: путь $PREFIX, права, переменные окружения, запуск оболочки. Подготовка уходит одной командой в exec-канал — комментарий в ShellBootstrap.kt уточняет, что это сделано намеренно: sshd Termux не любит держать отдельный канал на каждый опрос, поэтому bootstrap идёт через SshTransport.connect(..., bootstrap = ...), а основная сессия — один канал.

Удалённые хосты

SshTransport — SSH-транспорт; для каждого сервера из Room поднимается своя сессия. Пользователь переключается между хостами списком целей, поэтому можно держать открытыми, например, локальный Termux и два сервера и прыгать между ними.

Эмулятор и ANSI

ShellChatParser разбирает поток: escape-последовательности, OSC, CSI (parseEscape, parseOsc, parseCsi) и превращает их в строки AnsiLine (terminal/AnsiText.kt). Отрисовка — ui/shellchat/AnsiRenderer.kt, палитра ANSI — terminal/AnsiPalette.kt. Разбор один и тот же для терминального и чат-вида.

В состоянии сессии (ShellSession.kt) видно признаки, ради которых экран существует: inMode (режим cursor addressing), underTmux, tui, mouse, terminalViewVisible, emulatorColumns/emulatorRows против targetColumns/ targetRows (размеры эмулятора и что заявил клиент), scrollPosition, history, commandId, running/done. То есть экран умеет сообщать агенту, что идёт TUI-программа под tmux, включён режим мыши или терминал «застрял» в альт-режиме.

Доп. клавиши

ExtraKeysBar — то, без чего терминал на телефоне неудобен:

  • фиксируемые модификаторы CTRL и ALT (кнопка остаётся нажатой, пока включена, добавляется в набор чипов);
  • ESC и TAB;
  • цифры и стрелки;
  • компактный режим — переключатель в prefs shell_extra_keys_compact, размеры чипов 12sp / 10sp;
  • автоповтор: первое нажатие через REPEAT_START_MS = 400, далее шаг REPEAT_STEP_MS = 80.

В коде есть важная деталь про TUI: комментарий упоминает, что приложение должно отправлять те же escape-последовательности (ESC[1;5A и т. п.), какие ожидает TUI-программа, — иначе tmux и полноэкранные утилиты ломают раскладку клавиш.

Жесты

Отдельными моделями вынесены TerminalSwipeModel, PinchZoomModel, FontZoomModel, MouseWheel и ShellGeometry: свайп по горизонтали — прокрутка история, вертикаль — прокрутка, пинч — масштаб шрифта, колесо мыши — прокрутка. AltScreenScanner и ShellTargets — вспомогательные сканеры состояния.

5. Данные: БД, файлы, настройки

ЧтоГде лежитКак меняетсяКто читает
Список серверовRoom (remoteServerDao.observeAll)Экран серверовShellSessionManager.applyServers
Сессии и целиТолько в памяти, ConcurrentHashMapСоздание при подпискеЭкран терминала
Компактность доп. клавишprefs shell_extra_keys_compactЭкранExtraKeysBar
Прочее (шрифт, чат-вид)ui/shellchat/ShellChatPrefs.ktЛист настроек чат-видаShellChatViewModel
ЛогиfilesDir/log.txt через FileLogАвтоматическиdev_log {source:"app"}

Сессии не сохраняются между перезапусками приложения: пересоздаётся ShellSessionManager, и все сессии поднимаются заново.

6. Backend: REST/роуты

Своих роутов у инструмента нет. Терминал работает через локальный PTY Termux и SSH, а список хостов приходит из Room, который синхронизируется с бэкендом (/api/v1/servers/* — см. инструмент «Серверы» и ../architecture.md §6). Логи терминала, если их читает агент, идут через GET /api/v1/log.

7. Мост и MCP

Команда/тулЧто делаетОткуда вызывается
app_shellзапуск команды в shell-сессииСкилл y83-bridge, разработка
app_ui_action / app_ui_typeввод текста в элементы, включая поле терминалаСкилл y83-bridge
app_navigate с screen: "terminal"открыть экранBridgeScreenCatalog.kt
app_screenshotснимок экрана терминалаscreen_look, browser_look

Команды app_shell входят в группу app реестра BridgeCommands.kt (полный список — app_commands). Отдельных MCP-тулов «выполнить в терминале» в инвентаре /mcp нет: работа с shell идёт либо мостом, либо самим агентом через свой файловый доступ.

8. Настройки, конфиг, квоты и лимиты

ПараметрЗначениеГде задаётся
Автоповтор клавиш400 мс старт, 80 мс шагExtraKeysBar
Размер чипов12sp / 10sp компактExtraKeysBar
Ожидание DAO при стартедо 30 попыток, 1 сShellSessionManager.start
ТранспортPTY (локально) и SSH (удалённо)ShellSession, SshTransport

9. Ловушки и ограничения

  • Сессии не переживают перезапуск приложения. Работа в фоне оболочки сохраняется, но состояние экрана — нет.
  • sshd Termux капризен к каналам. Отсюда один канал на сессию и bootstrap одной командой; добавление «ещё одного опроса» в этой части ломает коннект.
  • Зависимость от готовности Room. Первые секунды после запуска список целей может быть неполным (подписка ждёт DAO) — это ожидаемо, а не баг.
  • TUI и tmux требуют точных escape-последовательностей. Самодельные «красивые» сочетания клавиш ломают полноэкранные программы.
  • Экран вывода (ShellOutput) только для чтения — отличить от рабочего терминала легко по отсутствию поля ввода.
  • Чат-вид разбирает ANSI по эвристикам. Нестандартные последовательности (не CSI/OSC/ESC) могут попасть в текст как есть.

10. Источники правды

  • app/src/main/java/com/y83/ws/terminal/ShellSessionManager.kt — сессии и цели.
  • app/src/main/java/com/y83/ws/terminal/ShellSession.kt — состояние сессии, PTY/SSH.
  • app/src/main/java/com/y83/ws/terminal/SshTransport.kt, ShellBootstrap.kt — транспорт и bootstrap.
  • app/src/main/java/com/y83/ws/terminal/TermuxLocalSetup.kt — локальное окружение Termux.
  • app/src/main/java/com/y83/ws/terminal/ShellChatParser.kt, AnsiText.kt, AnsiPalette.kt — разбор и рендер ANSI.
  • app/src/main/java/com/y83/ws/ui/terminal/ — панель, жесты, доп. клавиши.
  • app/src/main/java/com/y83/ws/ui/shellchat/ — чат-вид (экран, VM, лента, ввод, настройки).
  • app/src/main/java/com/y83/ws/ui/navigation/Screen.kt:123, MainRouter.kt:528,535 — маршруты.

Источник: docs/project/hub/03-terminal.md · Инструменты · 1 474 строк в 5 файлах. Страница собирается из документации проекта при сборке сайта.