25771a0c33
ci / JVM build + tests (push) Failing after 1m57s
PlantUML diagrams for future agent architecture (Android, multi-user chat, sub-agents, A2A): - 01-module-layers.md — целевая модульная структура - 02-agent-composition.md — AgentBuilder DSL + MemoryBackend.exposesTools() - 03-multi-user-chat.md — mention-detection sequence - 04-sub-agents.md — spawnChild + Flow<SubAgentEvent> + A2A - 05-android-stack.md — что меняется на Android vs Standalone Каждый .md включает пред-рендеренный SVG (показывается во всех markdown viewers без PlantUML plugin) + PlantUML source в code block (для редактирования). SVG нужен потому что PlantUML требует Graphviz dot для рендеринга — без него IntelliJ/VSCode выдают ошибку. Регенерация SVG после правки PlantUML-source: docker run --rm -v "$PWD:/work" plantuml/plantuml -tsvg /work/docs/diagrams/*.md
172 lines
5.9 KiB
Markdown
172 lines
5.9 KiB
Markdown
# 05 — Android Agent Stack
|
||
|
||
Что меняется vs `:standalone`. Цель: `BaseAgent` тот же самый, но platform-impl разные (Storage, LLM, Vector Memory, MCP).
|
||
|
||

|
||
|
||
PlantUML source (для редактирования; требует Graphviz `dot` для рендеринга):
|
||
|
||
```plantuml
|
||
@startuml android-agent-stack
|
||
skinparam componentStyle rectangle
|
||
|
||
title Android Agent Stack — что меняется vs Standalone
|
||
|
||
' --- Android side ---
|
||
package "Android Application" {
|
||
[MainActivity\n(Compose)] as Activity
|
||
[AndroidAgentRunner\n(workmanager / service)] as Runner
|
||
[AndroidAgentBuilder] as AndroidBuilder
|
||
}
|
||
|
||
package "Android-specific impls" {
|
||
[StorageSqliteAndroid\n(Room/sqlite)] as StorageA
|
||
[MemoryVectorAndroid\n(ONNX runtime + ANN)] as MemVecA
|
||
[LitertAndroid\n(NNAPI delegate)] as LitertA
|
||
[SoulFileAndroid\n(context.filesDir)] as SoulA
|
||
[McpRegistry\nstdio: ProcessBuilder] as McpA
|
||
}
|
||
|
||
' --- Shared (KMP) ---
|
||
package "Agent Runtime (shared)" {
|
||
[AgentCore\nBaseAgent] as AgentCore
|
||
[AgentBuilder] as Builder
|
||
}
|
||
|
||
package "Domain (shared)" {
|
||
[LlmTools\ncommonMain] as LlmT
|
||
[BackgroundEvents\ncommonMain] as Ev
|
||
[McpBridge\njvmMain] as McpB
|
||
[Skills\ncommonMain] as Skills
|
||
}
|
||
|
||
package "Memory (shared impl)" {
|
||
[MemoryMd\n(commonMain)] as MemMd
|
||
[MemoryApi\ninterfaces] as MemApi
|
||
}
|
||
|
||
' --- Зависимости ---
|
||
Activity --> Runner
|
||
Runner --> AndroidBuilder
|
||
AndroidBuilder --> AgentCore
|
||
|
||
AndroidBuilder --> StorageA
|
||
AndroidBuilder --> MemVecA
|
||
AndroidBuilder --> LitertA
|
||
AndroidBuilder --> SoulA
|
||
AndroidBuilder --> McpA
|
||
|
||
AgentCore --> LlmT
|
||
AgentCore --> Ev
|
||
AgentCore --> McpB
|
||
AgentCore --> Skills
|
||
AgentCore --> MemMd
|
||
|
||
' --- Главные отличия от Standalone ---
|
||
note right of LitertA
|
||
On-device inference.
|
||
LiteRT с NNAPI delegate →
|
||
работает на CPU/GPU/NPU
|
||
прямо на устройстве, без сети.
|
||
|
||
vs Standalone: HTTP-only
|
||
(OpenAI-compatible).
|
||
end note
|
||
|
||
note right of StorageA
|
||
android.database.sqlite
|
||
через Room или сырой API.
|
||
|
||
vs Standalone: JDBC +
|
||
Sqlite-JDBC driver
|
||
(только JVM).
|
||
end note
|
||
|
||
note right of MemVecA
|
||
JVector JVM-only. На Android
|
||
нужна альтернатива —
|
||
ONNX Runtime + какой-нибудь
|
||
ANN (Annoy/HNSW).
|
||
|
||
Или пока без vector memory,
|
||
только MemoryMd.
|
||
end note
|
||
|
||
note right of McpA
|
||
MCP через ProcessBuilder
|
||
на Android работает, но
|
||
subprocess lifecycle
|
||
сложнее (foreground service
|
||
нужен для долгого subprocess).
|
||
end note
|
||
|
||
@enduml
|
||
```
|
||
|
||
## Что общего с `:standalone`
|
||
|
||
**`BaseAgent`, `BackgroundScheduler`, `LlmTools`, `McpBridge`, `Skills`, `MemoryMd` — всё KMP (commonMain).** Android-agent = `:standalone` с другим wiring'ом. Не нужно переписывать agent logic.
|
||
|
||
## Что другое
|
||
|
||
| Компонент | `:standalone` (JVM) | `:agentik-android` (Android) | Сложность |
|
||
|---|---|---|---|
|
||
| Storage | `:storage-sqlite` (JDBC + Sqlite-JDBC) | `:storage-sqlite-android` (Room или raw) | Низкая — тот же `StorageBundle` interface |
|
||
| LLM | `:litert-openai` (HTTP), `:litert-google` (LiteRT JVM) | `:litert-android` (LiteRT Android, NNAPI delegate) | Средняя — нужен новый модуль |
|
||
| Vector memory | `:memory-vector` (JVector) | `:memory-vector-android` (ONNX Runtime + HNSW/Annoy) | Высокая — JVector JVM-only, нужна альтернатива |
|
||
| SOUL provider | `FileSoulProvider` (path) | `SoulFileAndroid` (`context.filesDir`) | Низкая |
|
||
| MCP | `McpRegistry` (ProcessBuilder, stdio subprocess) | Тот же `McpRegistry`, но subprocess в foreground service | Средняя — нужен Android service |
|
||
| Embedding | `HttpEmbeddingClient` (HTTP) | Тот же ИЛИ on-device (ONNX) | Средняя |
|
||
|
||
## Минимальный Android agent (v1)
|
||
|
||
Если не нужны все фичи сразу — минимум:
|
||
|
||
```kotlin
|
||
val agent = androidAgentBuilder(context) {
|
||
llm(LitertAndroid.onDevice(context, modelPath = "/data/local/tmp/model.litertlm"))
|
||
storage(SqliteStorage.android(context, "agent.db"))
|
||
memory(MemoryMd.root(context.filesDir.resolve("memory")))
|
||
soul(FileSoul(context.filesDir.resolve("SOUL.md")))
|
||
background {
|
||
// OnClosing + OnCompaction работают так же как на JVM
|
||
}
|
||
}
|
||
```
|
||
|
||
Без MCP, без vector memory (только MemoryMd на файлах), только on-device LLM. Достаточно для off-line агента.
|
||
|
||
## Foreground service для MCP
|
||
|
||
Если нужны MCP-серверы (например, локальный file-system MCP) — subprocess нужен foreground service чтобы Android не убил его при выключении экрана. Это добавляет сложности:
|
||
|
||
```kotlin
|
||
class McpForegroundService : Service() {
|
||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||
startForeground(NOTIFICATION_ID, notification)
|
||
val proc = ProcessBuilder(command, args).start()
|
||
// ... route stdio to McpLiteToolAdapter ...
|
||
return START_STICKY
|
||
}
|
||
}
|
||
```
|
||
|
||
Пока можно без этого (только если MCP нужен на Android).
|
||
|
||
## Текущее состояние vs целевое
|
||
|
||
✅ KMP-ready:
|
||
- `:llm-tools` (commonMain, платформо-агностик)
|
||
- `:mcp-bridge` (jvmMain — Android-вариант через `:mcp-bridge-android`)
|
||
- `:skills` (commonMain)
|
||
- `:memory-md` (commonMain)
|
||
- `:proto` (commonMain)
|
||
|
||
⏳ Не существует:
|
||
- `:storage-sqlite-android`
|
||
- `:memory-vector-android`
|
||
- `:litert-android`
|
||
- `:agentik-android` (само приложение)
|
||
- `:agent-core` (выделить BaseAgent + builder)
|
||
- `:background-events` (выделить events + scheduler)
|