Files
lpra/docs/superpowers/specs/2026-10-15-workspace-design.md
T

19 KiB

LPRA 0.2.0 — рабочее пространство (подпроект 1)

Дата: 2026-10-15. Статус: спецификация утверждена. Подпроект 2 (встроенный ИИ-помощник) — отдельная спецификация, делается после этого.

Цель

Работа с несколькими машинами в одном месте, без потери открытых терминалов при переходах по панели. Терминалы, файловые менеджеры (своих машин и по SSH) живут во вкладках одного рабочего пространства; файлы перетаскиваются между панелями и в терминал.

Критерии готовности:

  • переход Машины ↔ Терминал ↔ Настройки не обрывает сессии терминалов и не сбрасывает вкладки;
  • перезагрузка страницы сбрасывает пространство (с предупреждением браузера, если есть живые сессии);
  • файловый менеджер — тип панели во вкладке, в том числе по SSH;
  • перетаскивание файлов: между файловыми панелями (окно «переместить / копировать»), в терминал той же машины (вставка путей), в терминал другой машины — запрет с сообщением.

Решения, принятые в обсуждении

вопрос решение
Страницы «Порты», «Статус», «Изменить» окна поверх текущей страницы
Файлы рядом с терминалами в одной вкладке да: любая из до 4 панелей — терминал, SSH-терминал, файлы, SSH-файлы
Перезагрузка при живых сессиях вопрос браузера «Покинуть сайт?»
Архитектура одностраничная оболочка, остальное — HTML-фрагменты с сервера (вариант A)
Файлы по SSH без SFTP-библиотеки: команды на хосте через SSH, как у существующей передачи tar
Состояние одно на вкладку браузера, в памяти страницы; не сохраняется при перезагрузке

1. Каркас и маршруты

Оболочка. Адреса /, /terminal, /settings отдают один шаблон app.html: шапка (LPRA, «Машины · Терминал · Настройки» — «Настройки» только администраторам, статус активной панели, аккаунт) и три области <section data-view="machines|terminal|settings">. Старые адреса /agents/{id}/terminal и /agents/{id}/files отдают ту же оболочку и при загрузке создают вкладку нужного типа для этой машины (закладки не ломаются).

Роутер (static/app.js, без библиотек):

  • перехватывает клики по внутренним ссылкам и popstate; меняет видимую область через history.pushState, подсвечивает пункт шапки;
  • область «Терминал» создаётся один раз и потом только скрывается (hidden) — сессии, WebSocket и xterm живут, пока жива вкладка браузера;
  • «Машины» и «Настройки» при каждом показе подгружаются заново как фрагмент: GET /?frag=1, GET /settings?frag=1.

Фрагменты на сервере. render() получает режим фрагмента (параметр frag=1): шаблон отдаёт только содержимое, без <html>, шапки и подключений. Общая разметка head и topbar, сейчас скопированная в каждый шаблон, выносится в {{define}}-блоки.

Формы во фрагментах (app.js, перехват submit внутри областей и окон):

  1. onsubmit-обработчики (confirm(...)) срабатывают как обычно; отказ — ничего не происходит;
  2. форма отправляется через fetch (redirect: 'follow', тело — FormData);
  3. итоговый адрес ответа определяет, что перерисовать: тот же фрагмент по этому адресу (сохраняются ?err=..., ?updated=1, #users);
  4. формы на /logout и ссылки наружу работают обычной загрузкой страницы.

Скрипты фрагментов. Встроенные <script> во фрагментах не исполняются. Поведение страниц оформляется модулями с mount(root) / unmount(), которые вызывает роутер: копирование команд и коды установки (настройки), users.js, список машин с опросом присутствия. pin.js, scroll.js, account.js подключаются один раз в оболочке.

Предупреждение при уходе. beforeunload спрашивает «Покинуть сайт?», только если в рабочем пространстве есть живая сессия терминала или SSH-терминала.

2. Рабочее пространство и типы панелей

Модель. Вкладка содержит 1–4 панели в существующих раскладках (1, h, v, сетка), с изменением размеров и перетаскиванием панелей и вкладок, как сейчас. Тип панели:

тип что это
term терминал на машине (как сейчас)
ssh SSH-терминал через машину (как сейчас)
files файловый менеджер на машине
sshfiles файловый менеджер на SSH-хосте через машину

Разделение кода (сейчас всё в terminal.js и files.html):

  • workspace.js — вкладки, раскладки, разделение, перетаскивание панелей и вкладок, меню «+». С панелями работает через общий интерфейс: el, kind, agent, title, state и text (точка и строка статуса), fit(), focus(), close(), acceptsDrop(item), drop(item);
  • termpane.js — нынешний класс Session (терминал и SSH-терминал), вынесенный почти без изменений;
  • filepane.js — файловая панель (часть 3);
  • fileviews.js — общие окна файлов (просмотр и правка, hex, свойства, перемещение, загрузка, редактор SQLite).

Меню «+» (на компьютере и телефоне):

  • «Терминал ›» — «здесь (машина)», другие машины в сети, «SSH-хост…»;
  • «Файловый менеджер ›» — «здесь (машина)», другие машины в сети, «SSH-хост…».

«SSH-хост…» открывает существующее окно SSH-подключения; тип панели зависит от пункта меню. Последний SSH-хост (без секретов) запоминается, как сейчас.

Из списка машин: кнопка терминала → новая вкладка-терминал этой машины и переход в «Терминал»; кнопка файлов → новая вкладка «Файлы». Если пространства ещё нет, оно создаётся.

Заголовки. Вкладка файлов — иконка папки и машина · папка, путь обрезается слева, обновляется при смене папки. Переименование двойным кликом — как у терминалов. Точка статуса файловой панели — машина в сети / офлайн / ошибка.

Телефон. Вкладки и меню те же; разделения и перетаскивания, как и сейчас, только на компьютере.

3. Файловая панель

Содержимое нынешней страницы файлов как компонент FilePane(source): строка пути, «Вверх», «Обновить», «Папка / Файл / Загрузить», таблица с отметками, «В zip», «Удалить выбранное», загрузка перетаскиванием из ОС. Состояние (текущая папка, список, отметки) — у экземпляра; элементы ищутся внутри корня панели, без глобальных id. Две файловые панели в одной вкладке не мешают друг другу.

Общие окна (fileviews.js) — одно на страницу. При открытии окну передаётся панель-источник: машина или SSH, путь, что обновить после действия.

Источник данных — один интерфейс (list, read, write, mkdir, delete, move, copy, stat, chmod, download, upload) с двумя реализациями:

  • машина — существующий /api/panel/agents/{id}/fs/...;
  • SSH-хост — новые задачи агента sshfs.* (ниже).

Узкие панели (меньше ~520 px, в разделённой вкладке): прячется колонка «Изменён», кнопки строки сворачиваются в меню «⋯» — как сейчас на телефоне.

Файлы по SSH (sshfiles)

Агент держит одно SSH-подключение на панель: sshConnect и проверка ключа хоста из SSH-терминала. Подключение открывается при создании панели (окно «SSH-хост…»), получает id, закрывается при закрытии панели или через 10 минут простоя. Секреты передаются агенту один раз, панель их не хранит.

Операции — команды на хосте, пути в одинарных кавычках (shq):

операция команда
список stat по содержимому папки; формат выбирается один раз при подключении: GNU/busybox stat -c, BSD/macOS stat -f; без stat — разбор ls -la без точного времени
чтение, скачивание cat -- 'файл', поток через stdout
запись, загрузка cat > 'файл.tmp' && mv 'файл.tmp' 'файл', поток через stdin
папка, удаление, переименование mkdir -p, rm -rf, mv
права, владелец chmod, chown
копирование, перенос внутри хоста cp -a, mv
перенос между хостом и машинами существующая передача tar по SSH

Новые задачи агента: sshfs.open (подключиться, вернуть id и домашнюю папку), sshfs.close, sshfs.list, sshfs.read, sshfs.write, sshfs.mkdir, sshfs.delete, sshfs.move, sshfs.copy, sshfs.stat, sshfs.chmod, sshfs.send (скачивание через существующие куски xfer), sshfs.put (загрузка через куски xfer). Серверу — те же правила доступа, что у файловых операций машины; изменения пишутся в аудит.

Не входит: zip и распаковка на SSH-хосте, редактор SQLite по SSH — эти кнопки в sshfiles скрыты. Новых зависимостей нет.

4. Перетаскивание

Что тащится: строка файла или папки; если строка отмечена — все отмеченные строки панели. У курсора бейдж (имя или «N элементов»). Механизм — на pointer-событиях внутри страницы, тот же, что уже двигает вкладки и панели; подсказка над целью говорит, что произойдёт.

цель результат
другая файловая панель (любая машина или SSH-хост) небольшое окно у места броска: «Переместить / Копировать / Отмена», куда (папка цели), «если уже есть: сообщить ▾». Внутри машины — fs.copy; внутри SSH-хоста — cp/mv; между разными — существующая передача tar с прогрессом в этом же окне
папка в списке панели то же, цель — эта папка
терминал той же машины / того же SSH-хоста пути в одинарных кавычках через пробел вставляются в терминал, без Enter
терминал другой машины цель подсвечивается красным, подсказка «Нельзя: файл на X, терминал на Y»
заголовок вкладки через 0,5 с наведения вкладка активируется, бросить можно в её панель
пустое место / Esc отмена

Правила конфликтов имён — те же, что в окне «Переместить или копировать». Загрузка из ОС перетаскиванием — в любую файловую панель. На телефоне перетаскивания нет; остаётся окно перемещения с выбором машины или SSH.

5. Окна машины

«Порты», «Статус», «Изменить» — нынешние страницы как фрагменты (?frag=1) в общем окне machinedlg (заголовок «машина · раздел», закрытие; на телефоне — на весь экран). Открываются из кнопок строки в списке машин и из меню заголовка вкладки или панели (её машина). Формы — перехватом из части 1; результат (например, обновления клиента) показывается в окне. Живые части (графики и опрос статуса, тест скорости, присутствие) — модули mount / unmount; при закрытии окна останавливаются.

Ошибки и крайние случаи

  • Машина офлайн: терминал — как сейчас; файловая панель — «машина офлайн» и «повторить», при возвращении машины обновляется сама.
  • Нет доступа (роль «пользователь»): чужих машин нет в меню и списке; если доступ отобран при открытой вкладке — панель показывает «нет доступа».
  • Сессия истекла (401 или редирект на /login): сообщение и переход на вход.
  • Агент без sshfs.*: пункт «Файлы по SSH» сообщает «обновите агента».
  • Фрагмент не загрузился: ошибка и «повторить» в его области, остальное приложение работает.
  • SSH-подключение файловой панели оборвалось: следующая операция переподключается один раз; не вышло — панель сообщает и предлагает переподключиться.

Проверка

На стенде (сервер, агент, тестовый sshd), Chrome на компьютере и в эмуляции телефона:

  1. Переходы Машины ↔ Терминал ↔ Настройки при идущем выводе в терминале — вывод не прерывается; «Назад / Вперёд»; перезагрузка — сброс и «Покинуть сайт?».
  2. Вкладки с терминалом, файлами, SSH-файлами; разделение, изменение размеров, перетаскивание панелей и вкладок.
  3. Файловая панель машины и SSH-хоста: список, просмотр, правка, загрузка, скачивание, создание, удаление, переименование, права.
  4. Перетаскивание: в соседнюю панель (своя машина, SSH), в папку, в терминал той же машины (вставка путей), в терминал чужой (запрет).
  5. Окна машины: формы, обновление клиента, остановка графиков при закрытии.
  6. Роли: обычный пользователь видит в меню и списке только свои машины.
  7. Регрессия: PIN, ключи доступа, установщик, редактор SQLite, перенос на другие машины, прямой адрес.

Версия и документация

Версия 0.2.0. README — разделы о рабочем пространстве, файлах по SSH и перетаскивании.