LLM Text Rewrite
Relevant source files
The following files were used as context for generating this wiki page:
- app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/rewrite/LlmRewriteManager.kt
- app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/rewrite/LlmRewriteClient.kt
- app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/rewrite/RewriteOptionsPanel.kt
- AGENTS.md
- VOXTRAL_KEYBOARD_PLAN.md
- app/src/main/res/values/strings.xml
The LLM Text Rewrite system is a core feature of the Ownkey Keyboard that allows users to leverage Large Language Models (LLMs) to modify, refine, or transform selected text directly within the keyboard interface. It follows a "Bring Your Own Key" (BYOK) model, where users provide their own API keys for various AI providers, ensuring privacy and user control over the AI backend.
Sources: AGENTS.md:15, VOXTRAL_KEYBOARD_PLAN.md:1-10
Architectural Overview
The rewrite system is composed of three primary layers: the UI layer (Options Panel), the Management layer (Manager), and the Network layer (Client). It utilizes a secure storage mechanism for API keys and integrates with the Android Input Method Editor (IME) instance to manipulate text in active editor fields.
System Components
| Component | Description |
|---|---|
LlmRewriteManager | Orchestrates the rewrite flow, resolves text targets, and updates the UI state. |
LlmRewriteClient | Handles HTTP communication, request preparation (payload building), and response parsing for different AI providers. |
RewriteOptionsPanel | The Compose-based UI component where users select rewrite "voices" (presets) or custom instructions. |
LlmRewriteSecretsStore | Provides Android Keystore-backed local storage for sensitive API keys. |
Sources: LlmRewriteManager.kt:33-45, LlmRewriteClient.kt:29-40, AGENTS.md:15-18
Data Flow and Interaction
The rewrite process is triggered when a user selects text (or has an active cursor near text) and chooses a rewrite option. The system follows a structured sequence from target resolution to committing the AI-generated text.
Rewrite Sequence Diagram
The following diagram illustrates the interaction between the user interface, the manager, and the external LLM provider.
Text Target Resolution
The LlmRewriteManager contains logic to determine exactly which text should be sent to the LLM. It supports two modes:
- Selection Mode: If the user has manually selected a block of text, that specific range is targeted.
- Cursor/Inference Mode: If no text is selected, the manager attempts to infer the target by looking at the text before the selection (up to the last sentence boundary or newline).
private fun resolveRewriteTarget(): Result<RewriteTarget> {
val content = editorInstance.activeContent
val selection = content.selection
// ... logic for selected text ...
val textBefore = content.textBeforeSelection
val lastBoundary = sentenceEnd.lastIndexOfAny(charArrayOf('\n', '.', '!', '?'))
// ... logic to calculate absolute start/end ...
}
Sources: LlmRewriteManager.kt:89-138
AI Provider Integration
The LlmRewriteClient is designed to be compatible with multiple AI provider interfaces. It dynamically builds request payloads and headers based on the configured provider ID.
Supported Provider Types
The client handles different API structures through specific payload builders:
- OpenAI Responses: Uses the
/v1/responsesstructure withinstructionsandinputfields. - Anthropic: Uses the
messagesstructure withsysteminstructions and specific version headers (anthropic-version). - Chat Completions (Generic): Uses the standard OpenAI-compatible
/v1/chat/completionsformat with a system and user message array.
Sources: LlmRewriteClient.kt:130-185
Configuration Options
Users can configure the following parameters in the "AI" settings screen:
| Parameter | Default Value | Description |
|---|---|---|
Endpoint URL | https://api.openai.com/v1/responses | The URL for the AI service. |
Model | gpt-5.5 | The specific model ID to use for processing. |
Provider ID | OpenAiResponses | Inferred from URL if blank; determines payload format. |
API Key | (Empty) | Stored encrypted via Android Keystore. |
Sources: LlmRewriteClient.kt:41-43, strings.xml:510-530
Error Handling and Retries
The client implements a retry mechanism for transient network or server errors. It specifically targets status codes like 408 (Request Timeout), 429 (Too Many Requests), and 5xx (Server Errors).
Conclusion
The LLM Text Rewrite system provides a flexible and secure framework for AI-assisted text editing. By decoupling the interface from specific AI providers and ensuring that API keys are stored in the Android Keystore, Ownkey Keyboard maintains its commitment to user privacy while offering advanced features. The architecture allows for easy extension to new LLM providers by simply adding new payload builders and extraction logic within the client.