d5aa844fa0
- design/mockups/ — 15 макетов (одно состояние = один файл), из /tmp перенесены в репо - design/screenshots/ — те же экраны PNG - design/PRINCIPLES.md — принципы: что берём у десктопа, что на телефоне иначе - design/BORROW.md — что откуда: ядро (Nexus), тема (десктопный макет), отрисовка Markdown (ai/assistent) - design/gen_mockups.py — генератор макетов, путь вывода теперь рядом с ним - README: разделы «Принципы» и «Откуда код» со ссылками
148 lines
8.9 KiB
Markdown
148 lines
8.9 KiB
Markdown
# Что откуда взято
|
||
|
||
**Правило простое:** чужое не переписываем заново, а берём и говорим, откуда
|
||
взяли. Ниже по каждому куску: откуда, что именно, и что с ним делать на телефоне.
|
||
|
||
| Куски кода | Откуда | Состояние |
|
||
|---|---|---|
|
||
| Ядро агента | `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:
|
||
|
||
```kotlin
|
||
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 нет**. Вместо
|
||
этого системный переход:
|
||
|
||
```kotlin
|
||
context.startActivity(Intent(Intent.ACTION_VIEW, url.toUri()))
|
||
```
|
||
|
||
### Зависимость
|
||
|
||
Одна, и она уже есть в нашем Nexus:
|
||
|
||
```kotlin
|
||
implementation("ru.otpbank.ai:markdown:0.51.0")
|
||
```
|
||
|
||
Плюс репозиторий в `build.gradle.kts` — без него не соберётся:
|
||
|
||
```kotlin
|
||
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`.
|
||
|
||
---
|
||
|
||
## Про доступы
|
||
|
||
Адрес и токен агента — **настройки приложения**, вводятся человеком, в коде
|
||
репозитория их нет и быть не должно. В историю коммитов секреты не попадают.
|