A Kotlin Multiplatform AI workspace built around an explicit context pipeline.
Module status · What works today · Context pipeline · 中文文档
FatAI is a work-in-progress AI assistant. The codebase is organized as KMP feature modules so chat, prompts, memory, files, workspaces, models, knowledge, tools, and agents can evolve independently. This document describes what is in the repository today, not the planned end state.
- Android
- Desktop JVM
- iOS (
iosArm64andiosSimulatorArm64) - A small Ktor server module is present as a sample endpoint; it is not an AI proxy or backend.
The application UI is Compose Multiplatform. SQLDelight drivers and Ktor engines are supplied from platform source sets, while feature APIs and domain code live in commonMain.
| Module | Current implementation | Status |
|---|---|---|
core |
ChatItemType, MessageContentType, provider types, and shared chat primitives. |
Implemented |
database |
SQLDelight schema; Android, JVM, and iOS drivers; migrations through version 5. | Implemented |
feature-chat |
Conversation/message repository: create, list, search, pin, archive, delete, persist and update messages. | Implemented |
feature-prompt |
Ordered ContextEngine, system/template/workspace/memory/file/history providers, and prompt-template persistence. |
Implemented; no template-management screen yet |
feature-memory |
Global/workspace/conversation memory storage and recall; model-backed summary service at 500 messages. | Implemented; no semantic search or memory-management UI |
feature-model |
ChatProvider contract, ModelGateway, API-key repository, Ktor clients, and one OpenAI-compatible streaming adapter. |
Implemented for OpenAI-compatible endpoints |
feature-files |
Portable attachment metadata, pending-to-message binding, and attachment persistence. | Implemented; content extraction is pending |
feature-workspace |
Default Personal workspace, create/select/update/archive repository operations, workspace instructions. | Implemented; editing/archive UI is pending |
feature-settings |
Persisted system/light/dark theme preference. | Implemented |
feature-knowledge |
Gradle/KMP module scaffold only. | Not implemented |
feature-tools |
Gradle/KMP module scaffold only. | Not implemented |
feature-agent |
Gradle/KMP module scaffold only. | Not implemented |
shared |
Temporary Koin composition and platform bootstrap bridge while migrations are completed. | Compatibility layer; do not add new feature logic |
composeApp |
Decompose root navigation, chat/settings UI, resources, platform entry points, and responsive layouts. | Implemented |
The project includes all planned feature modules, but Knowledge, Tools, and Agent currently contain no domain contracts or runtime behaviour. They are intentionally listed as scaffolds rather than claimed as product features.
- Responsive Open WebUI-inspired layout: fixed desktop sidebar and mobile navigation drawer.
- Conversation create, search, pin, archive, delete, and automatic first-message title.
- SSE streaming, stop generation, regenerate, and continue generation.
- A streaming “Thinking…” indicator.
- Assistant Markdown rendering with GFM tables, links, code blocks, and mobile-oriented typography.
- Decompose stack navigation between Chat and Settings.
- System, light, and dark themes persisted in
AppSetting. - English and Chinese Compose resources selected from the system locale.
- FileKit picker for PDF, Office files, Markdown, text, and common image formats.
- Pending attachments are stored separately, then assigned to the user message on send.
- Sent images are previewed in chat through FileKit's KMP image integration; non-image attachments render as file cards.
- Reopening a conversation restores attachments beneath their original message.
Attachments are currently represented in the model context as a file manifest (name, MIME type, and size). The app does not yet upload file bytes to providers, extract PDF/text content, perform OCR, or send vision message parts.
- Add, activate, and delete API-key configurations with provider, base URL, and model fields.
- The active configuration is used for streaming chat requests.
- The implemented transport calls the OpenAI Chat Completions SSE shape:
POST {baseUrl}/chat/completions.
OpenAI, DeepSeek, OpenRouter, Ollama, and Custom can be configured when their endpoint is OpenAI-compatible. Gemini and Claude currently appear in the provider selector only as configuration presets; dedicated Gemini and Anthropic adapters have not been implemented, so those native APIs are not supported yet. API keys are stored in the local SQLDelight database; secure platform key storage is still pending.
Every outgoing chat request is assembled by feature-prompt in deterministic order:
System prompt
→ enabled prompt templates
→ current workspace instruction
→ recalled memory
→ conversation file manifest
→ most recent 20 chat messages
→ OpenAI-compatible model gateway
PromptProvider is the extension point. A future RAG provider, MCP tool-result provider, or agent state provider can join the pipeline without coupling itself to the chat screen.
MemoryEntry supports GLOBAL, WORKSPACE, and CONVERSATION scopes plus FACT and SUMMARY kinds. Recall is a SQL query limited to 20 entries. When a completed conversation reaches exactly 500 messages, ConversationMemoryService asks the configured model for a conversation summary and stores it as conversation-scoped memory.
There is no embedding generation, vector database, semantic recall, deduplication, or UI for authoring and reviewing memory yet.
ChatItemType identifies the sender (Question or Answer), while MessageContentType identifies the primary body (Text, Markdown, Image, File, ToolResult, or Thinking). contentType is persisted on ChatItem (migration 4).
FileAsset is the attachment sidecar. New attachments have a null messageId; on send, migration 5's messageId column binds them to the newly created user message. The UI groups assets by this ID, so image previews and file cards remain associated with the correct chat bubble. Only Text user input and Markdown assistant output are produced by the current chat flow; the other content types are reserved for later renderers.
composeApp (Compose UI, Decompose root, responsive screens)
│
├── shared (temporary Koin wiring and platform bootstrap)
│ ├── feature-chat / feature-model / feature-prompt
│ ├── feature-memory / feature-files / feature-workspace
│ └── feature-settings
│
├── core (shared primitives)
└── database (SQLDelight schema, migrations, platform drivers)
feature-knowledge / feature-tools / feature-agent
└── KMP scaffolds reserved for V2 implementation
composeApp is the application shell, not a feature module. Feature data and use cases are kept out of UI code where possible, but Koin composition remains in shared while the historical shared module is retired. New domain behaviour should go to the corresponding feature-* module.
Compose UI strings are in:
- English:
composeApp/src/commonMain/composeResources/values/strings.xml - Chinese:
composeApp/src/commonMain/composeResources/values-zh/strings.xml
Android's app name remains in Android resources under composeApp/src/androidMain/res/values*. The native iOS string tables live in iosApp/iosApp/{en,zh-Hans}.lproj/. Brand sources are assets/branding/fatai-icon.svg and assets/branding/fatai-banner.svg.
SQLDelight stores conversations, messages, provider configurations, workspaces, memory entries, prompt templates, file assets, and app settings. Desktop stores the database at ~/.fatai/app.db and copies a legacy ~/.ai-assistant/app.db on first launch when available. Android and iOS use their platform SQLDelight drivers.
# Desktop
./gradlew :composeApp:run
# Android APK
./gradlew :composeApp:assembleDebug
# Compile checks used for the KMP application
./gradlew :composeApp:compileKotlinJvm
./gradlew :composeApp:compileDebugKotlinAndroid
./gradlew :composeApp:compileKotlinIosSimulatorArm64
# Sample Ktor server
./gradlew :server:runOpen iosApp/ in Xcode to run the iOS app.
- Detekt is applied to every Gradle subproject using
config/detekt/detekt.yml. - Kover is applied to
composeAppfor JVM coverage reporting. - Tests exist only as minimal scaffolding and are not currently a delivery gate; compilation checks are the primary verification step during the architecture migration.
| Area | Library |
|---|---|
| UI | Compose Multiplatform 1.9.0 / Material 3 |
| Navigation | Decompose 3.3.0 |
| DI | Koin 4.1.1 |
| Network | Ktor Client 3.3.1 |
| Persistence | SQLDelight 2.1.0 |
| Files and images | FileKit 0.12.0, Coil 3.3.0 |
| Markdown | multiplatform-markdown-renderer-m3 0.37.0 |