Metadata-Version: 2.4
Name: kei-typing-assistant
Version: 0.1.0
Summary: AI-powered desktop typing assistant with real-time ghost-text completions, personalized via local embeddings and semantic example retrieval
Keywords: typing-assistant,ai,llm,autocomplete,productivity,ghost-text
Author: Sergei Konovalov
Author-email: Sergei Konovalov <l0kifs91@gmail.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: MacOS X
Classifier: Environment :: Win32 (MS Windows)
Classifier: Environment :: X11 Applications :: Qt
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Text Editors :: Text Processing
Requires-Dist: anthropic>=0.112.0
Requires-Dist: openai>=2.44.0
Requires-Dist: llama-cpp-python>=0.3.0
Requires-Dist: huggingface-hub>=1.21.0
Requires-Dist: fastembed>=0.8.0
Requires-Dist: pyqt6>=6.11.0
Requires-Dist: pynput>=1.8.2
Requires-Dist: qasync>=0.28.0
Requires-Dist: typer>=0.9.0
Requires-Dist: rich>=13.0.0
Requires-Dist: sqlalchemy>=2.0.0
Requires-Dist: alembic>=1.18.5
Requires-Dist: pydantic-settings>=2.14.2
Requires-Dist: loguru>=0.7.3
Requires-Dist: pydantic>=2.13.4
Requires-Dist: keyring>=25.7.0
Requires-Python: >=3.12
Project-URL: Homepage, https://github.com/l0kifs/kei-typing-assistant
Project-URL: Repository, https://github.com/l0kifs/kei-typing-assistant
Project-URL: Issues, https://github.com/l0kifs/kei-typing-assistant/issues
Project-URL: Changelog, https://github.com/l0kifs/kei-typing-assistant/releases
Description-Content-Type: text/markdown

# Kei Typing Assistant

An AI-powered desktop typing assistant that provides real-time text completions as ghost text via a floating overlay window, accessible from any application. Learns your writing style over time for increasingly personalized suggestions.

## Features

- Global hotkey opens a compact overlay window from any app; press it again to copy and close
- Streaming AI suggestions appear as faint ghost text while you type
- Accept a suggestion with `Tab`, dismiss with `Esc`
- Three AI providers: local LLM (llama.cpp, runs fully offline), MiniMax, and OpenRouter
- **Hybrid mode**: races the local model against a cloud provider and upgrades to the cloud result if it arrives first, within a configurable time window
- Model warm-up loads the local model in the background at startup so the first suggestion isn't slowed by a cold start
- Accepted suggestions are stored with semantic embeddings and retrieved as personalized few-shot context, with per-example search/shown counts tracked over time
- Manage stored examples (view, search, add, delete) from a dedicated GUI window
- Reusable, ordered **context fragments** — curated notes you can prepend to the AI system prompt — managed from their own GUI window
- Mid-word suppression skips AI requests while the cursor sits inside a word
- API keys stored securely in the system keychain
- SQLite storage with Alembic-managed schema migrations

## Requirements

- Python 3.12+
- macOS 12+ (primary), Windows 10/11, Linux supported
- API key for [MiniMax](https://www.minimaxi.com) or [OpenRouter](https://openrouter.ai) (not required for the default local LLM provider)
- macOS: Accessibility permission required for global hotkey

## Quick Start

### 1. Install

```bash
git clone https://github.com/l0kifs/kei-typing-assistant.git
cd kei-typing-assistant
uv sync
```

### 2. Configure (optional)

Create a `.env` file in the project root to override defaults:

```env
KEI__AI_PROVIDER=local_llm      # local_llm | minimax | openrouter
KEI__HOTKEY=ctrl+alt+space      # global hotkey
KEI__FLAVOUR="Concise, formal"  # personalization hint for AI
```

All settings with defaults are documented in [src/kei_typing_assistant/config/settings.py](src/kei_typing_assistant/config/settings.py).

### 3. Add your API key (cloud providers only)

If using MiniMax or OpenRouter, open Settings from the tray icon and enter your API key. Keys are stored in the system keychain — never in plaintext. The default local LLM provider needs no API key; the model is downloaded from Hugging Face on first run.

### 4. Grant Accessibility permission (macOS)

**System Settings → Privacy & Security → Accessibility** — add the app or your terminal to allow global hotkey capture.

### 5. Run

```bash
uv run kei
```

The app runs in the system tray. Press the hotkey (`Ctrl+Alt+Space` by default) to open the overlay.

## Usage

| Action | Key |
|--------|-----|
| Open overlay | `Ctrl+Alt+Space` (configurable) |
| Accept suggestion | `Tab` |
| Copy text & close | `Ctrl+Alt+Space` again |
| Dismiss without copying | `Esc` |

## AI Providers

| Provider | Setting value | Notes |
|----------|---------------|-------|
| Local LLM | `local_llm` (default) | Runs fully offline via llama.cpp; GGUF model auto-downloaded from Hugging Face; GPU-accelerated via Metal/CUDA where available |
| MiniMax | `minimax` | Cloud API, accessed via an Anthropic-compatible endpoint |
| OpenRouter | `openrouter` | Cloud API, accessed via an OpenAI-compatible endpoint; free-tier models available |
| Hybrid | enable `hybrid_mode` | Races the local model against a chosen cloud provider (MiniMax or OpenRouter) and swaps in the cloud result if it beats the local one within `hybrid_upgrade_window_s` |

## Settings Window

| Tab | Contents |
|-----|----------|
| General | Writing-style ("flavour") hint injected into the AI system prompt |
| AI Model | Provider selection (Local LLM / MiniMax / OpenRouter / Hybrid) and per-provider configuration (model, API key, context window, GPU layers, sampling params) |
| Behaviour | Suggestion length, temperature, debounce delay, mid-word suppression, include-context-fragments toggle |
| Appearance | Theme, ghost-text opacity, font family/size, overlay position |
| Hotkeys | Global hotkey binding |
| Storage | Data directory location (models, database) |

Two standalone windows, opened from the tray/settings menu, manage personalization data directly:

- **Context Fragments** — add, edit, reorder, search, and delete reusable prompt snippets prepended to the AI system prompt when enabled
- **Suggestion Examples** — browse, search, add, and delete the accepted (input → suggestion) pairs used for semantic few-shot retrieval, including how often each has been searched/shown

## Configuration Reference

| Setting | Default | Description |
|---------|---------|-------------|
| `KEI__HOTKEY` | `ctrl+alt+space` | Global trigger hotkey |
| `KEI__AI_PROVIDER` | `local_llm` | `local_llm`, `minimax`, or `openrouter` |
| `KEI__AI_MAX_TOKENS` | `60` | Max suggestion length |
| `KEI__AI_TEMPERATURE` | `0.8` | Sampling temperature |
| `KEI__AI_DEBOUNCE_MS` | `300` | Delay before AI request (ms) |
| `KEI__MID_WORD_SUPPRESSION` | `false` | Skip requests while the cursor is mid-word |
| `KEI__INCLUDE_CONTEXT_FRAGMENTS` | `false` | Prepend saved context fragments to the AI system prompt |
| `KEI__FLAVOUR` | `` | Writing style hint for AI |
| `KEI__THEME` | `system` | `system`, `dark`, or `light` |
| `KEI__HYBRID_MODE` | `false` | Race local LLM against a cloud provider |
| `KEI__HYBRID_UPGRADE_WINDOW_S` | `1.5` | Seconds to wait for the cloud provider before keeping the local result |
| `KEI__LOCAL_LLM_MODEL_ID` | `Qwen/Qwen2.5-3B-Instruct-GGUF` | Hugging Face repo for the local model |
| `KEI__LOCAL_LLM_N_GPU_LAYERS` | `-1` | GPU layers to offload (`-1` = all, `0` = CPU only) |
| `KEI__SEMANTIC_EXAMPLES_TOP_K` | `5` | Max similar accepted examples injected as few-shot context |
| `KEI__DATA_DIR` | `~/.kei_typing_assistant` | Base directory for models, database, and settings |

Full list of settings, defaults, and validation ranges: [src/kei_typing_assistant/config/settings.py](src/kei_typing_assistant/config/settings.py).

## Development

```bash
# Run tests
pytest

# Run tests with coverage
pytest --cov=src/kei_typing_assistant

# Lint & format
ruff check .
ruff format .
```

## CLI Reference

`kei-cli` provides a command-line interface for testing suggestions, managing the semantic example store, local models, database migrations, and configuration.

```bash
uv run kei-cli [--verbose] COMMAND [ARGS]
```

### Suggestion commands

| Command | Description |
|---------|-------------|
| `suggest TEXT` | Stream an AI suggestion for the given text |
| `accept TEXT SUGGESTION` | Save an accepted (input, suggestion) pair to the semantic example store |
| `test [--text TEXT]` | Full E2E flow: suggest → save accepted example |

**Typical workflow:**

```bash
# 1. Get a suggestion
uv run kei-cli suggest "The weather today is"
#   → warm and sunny with clear skies

# 2. Accept it — embeds and saves for future retrieval
uv run kei-cli accept "The weather today is" "warm and sunny with clear skies"
#   ✓ Saved: 'The weather today is' → 'warm and sunny with clear skies'

# 3. Next suggest call retrieves similar stored examples as context
uv run kei-cli suggest "The weather this morning is"
```

`suggest` options: `--flavour TEXT`, `--max-tokens INT`
`test` options: `--text TEXT`, `--flavour TEXT`, `--max-tokens INT`

### Local model

```bash
uv run kei-cli model list             # List downloaded models
uv run kei-cli model status MODEL_ID  # Check if a model is downloaded
uv run kei-cli model delete MODEL_ID  # Delete a downloaded model from disk
```

### Database

```bash
uv run kei-cli db upgrade   # Migrate the database to the latest schema revision
uv run kei-cli db current   # Show the currently applied schema revision
```

### Configuration

```bash
uv run kei-cli config show      # Show current configuration
```

## Architecture

The project follows Domain-Driven Design. See [docs/ddd-architecture-rules.md](docs/ddd-architecture-rules.md) for conventions and [docs/BRD.md](docs/BRD.md) for the business requirements behind it.

```
src/kei_typing_assistant/
├── main.py          # Composition root: wiring, bootstrap, launch
├── config/          # Settings & logging
├── domains/         # Pure business logic (suggestion, context_fragments, local_model)
├── infrastructure/  # AI provider clients, SQLite database + Alembic migrations, keychain
└── entry_points/    # Qt GUI, hotkey listener, tray, CLI, background workers
```

Database schema changes are managed with Alembic; migrations run automatically at startup (`kei-cli db upgrade` for manual control).

## Publishing

See [docs/PUBLISHING.md](docs/PUBLISHING.md). Releases are published to PyPI automatically via GitHub Actions on tag push. See [CHANGELOG.md](CHANGELOG.md) for release history.
