Раздел: 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 + все удалённые серверы из Room | ShellSessionManager.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— маршруты.