Files
subochev d5aa844fa0 design: макеты 15 экранов + принципы Android + откуда взят код
- design/mockups/ — 15 макетов (одно состояние = один файл), из /tmp перенесены в репо
- design/screenshots/ — те же экраны PNG
- design/PRINCIPLES.md — принципы: что берём у десктопа, что на телефоне иначе
- design/BORROW.md — что откуда: ядро (Nexus), тема (десктопный макет), отрисовка Markdown (ai/assistent)
- design/gen_mockups.py — генератор макетов, путь вывода теперь рядом с ним
- README: разделы «Принципы» и «Откуда код» со ссылками
2026-09-20 13:59:22 +03:00

8.9 KiB
Raw Permalink Blame History

Что откуда взято

Правило простое: чужое не переписываем заново, а берём и говорим, откуда взяли. Ниже по каждому куску: откуда, что именно, и что с ним делать на телефоне.

Куски кода Откуда Состояние
Ядро агента subochev/agentik → Nexus caffeine подключено
Скелет приложения, тема свой, в этом репозитории есть
Отрисовка Markdown ai/assistent ещё не перенесена
Макеты экранов свои, из десктопного дизайна лежат в design/

1. Ядро агента — берём из Nexus

Откуда: репозиторий https://git.binom.pw/subochev/agentik, модуль client. Библиотека публикуется в Nexus (репозиторий caffeine) — руками не публикуем, публикует CI/CD по релизу.

Что берём: pw.binom.agentik:client, версия задана в gradle/libs.versions.toml (agentik = "5").

Что важно знать про неё: движок библиотека не задаёт — он передаётся снаружи. На Android это OkHttp:

agentikHttpClient(OkHttp, token) { ... }   // ktor-client-okhttp уже подключён

Это не наша выдумка, а условие задачи: библиотека не должна тянуть на телефон чужой движок. Своя авторизация у agentik — отдельная, не копия A2A.

2. Скелет приложения и тема — своё

app/src/main/kotlin/pw/binom/agentik/android/ — написано в этом репозитории, коммит ef4804a («Скелет Android-клиента agentik»).

Тема (ui/theme/Color.kt, Theme.kt) — цвета согласованы с десктопным клиентом: они пришли из одобренного десктопного макета agentik-desktop/approved/001-sidebar-utility.html. Значения: фон #121218, панель #17212B, акцент #6AB2F2, текст #EBEBEB, приглушённый #768C9E, ошибка #EC3942.

Экраны обязаны читать MaterialTheme.colorScheme.*, а не палитру напрямую — чтобы позже появились другие темы без правки экранов (требование R1.1 десктопных требований).

3. Отрисовка Markdown — берём из ai/assistent

Откуда: https://git.binom.pw/ai/assistent (ветка main, проверено на коммите 2c5b3f9). Репозиторий приватный — скачивать по RAW-адресу с логином: https://git.binom.pw/ai/assistent/raw/branch/main/<путь>.

Писать своё не надо — надо взять это. Четыре файла:

Файл Строк Что внутри
client-shared/src/main/kotlin/pw/binom/client/shared/markdown/MarkdownSegment.kt 59 куски разметки: текст, блок кода, таблица, картинка, разделитель + стилевые участки
client-shared/src/main/kotlin/pw/binom/client/shared/markdown/MarkdownParserImpl.kt 353 parseMarkdown(markdown): List<MarkdownSegment>
client-shared/src/main/kotlin/pw/binom/client/shared/ui/MarkdownRendering.kt 377 сама отрисовка: inline-стили, ссылки, код с копированием, таблицы, картинки
client/src/main/kotlin/pw/binom/client/ui/MarkdownRenderer.kt 25 обёртка: открытие ссылки в браузере, parseMultiline — образец использования

Как переносить на Android

Модуль client-shared собран под Compose Desktop (JVM) — целиком как зависимость его взять нельзя, на телефоне не соберётся. Поэтому файлы копируются в наш модуль, а не подключаются.

Проверено по коду — переносятся почти дословно:

  • MarkdownSegment.kt, MarkdownParserImpl.kt — ни одной строки под JVM, Swing, AWT или Skiko. Чистая логика;
  • MarkdownRendering.kt — только androidx.compose.* и ни одного диалога и ни одного оконного примитива. Единственная платформенная мелочь — LocalClipboardManager (для копирования кода), на Android он есть.

Переделать придётся только одно: открытие ссылок. В четвёртом файле это java.awt.Desktop.getDesktop().browse(...) — на телефоне AWT нет. Вместо этого системный переход:

context.startActivity(Intent(Intent.ACTION_VIEW, url.toUri()))

Зависимость

Одна, и она уже есть в нашем Nexus:

implementation("ru.otpbank.ai:markdown:0.51.0")

Плюс репозиторий в build.gradle.kts — без него не соберётся:

maven {
    url = uri("http://192.168.76.117/repository/developerspace-prod-mvn-hosted/")
    isAllowInsecureProtocol = true
}

Что из assistent НЕ берём

MessageBubble.kt (789 строк, пузырь сообщения целиком) — тянет за собой модуль chat-common. Нам он не нужен: пузырь у нас свой, из макетов. Архитектуру, слои, готовые экраны (ChatScreen, SettingsDialog) и модули chat-* — тоже не берём, у нас своё (границы заимствования разобраны в десктопном репозитории: BORROW-FROM-ASSISTENT.md).

Приёмы отрисовки — самое ценное

В десктопном репозитории разобраны чужие грабли с указанием мест в коде: BORROW-FROM-ASSISTENT.md, раздел «Приёмы отрисовки». Читать до переноса. Главная из них: Box(horizontalScroll) внутри контейнера с бесконечной максимальной шириной (wrapContentWidth) роняет Compose с ошибкой measured with an infinity maximum width — таблицы размечаются парой разных режимов. На телефоне экран узкий, и это особенно чувствительно.

Состояние: файлы ещё не перенесены — это отдельная задача. Переносить из ai/assistent коммита 2c5b3f9 (свежее проверять там же).

4. Макеты экранов — свои, но выросли из десктопных

design/mockups/ — пятнадцать экранов, по одному состоянию на файл. Рисовались как продолжение одобренного десктопного дизайна (agentik-desktop/approved/001-sidebar-utility.html — «привычный мессенджер»), поэтому палитра, значки и порядок экранов совпадают с десктопом.

Чем отличаются — PRINCIPLES.md. Кратко: телефон всегда узкий, вместо «Назад внутри узкого окна» — системная кнопка и жест, вместо модальных окон — шторки снизу.

5. Принципы — не копируем, ссылаемся

Принципы (что видно на экране, группы, агенты, непрочитанные, «нет данных — нет цифры», сообщения как источник правды) описаны в десктопном репозитории: REQUIREMENTS.md, approved/README.md, THEMES.md, STORAGE.md, CACHE.md. Копий не делаем — один источник правды лучше двух, которые разъедутся. Отличия Android — в PRINCIPLES.md.


Про доступы

Адрес и токен агента — настройки приложения, вводятся человеком, в коде репозитория их нет и быть не должно. В историю коммитов секреты не попадают.