Rework AI-Typewriter en application d'arrière-plan multi-profils
- Rollback gestion d'équations : écriture littérale caractère par caractère (suppression de math_format.py et de la normalisation Unicode). - Nouveau profil par défaut 'Mathématiques (LaTeX)' : le modèle émet du LaTeX encadré [EQ]...[/EQ], intercepté par KeyStepper qui déclenche Alt+= en début d'équation et -> en fin. - Config multi-profils dans %APPDATA%/ai-typewriter/config.json (ConfigStore + profils par défaut auto-créés). - Icône de zone de notification (pystray) : Ouvrir les logs (temps réel), Ajouter/Modifier un profil, Gérer l'authentification, Quitter. - Sélecteur de modèles : modèles locaux Ollama + recherche/téléchargement depuis la bibliothèque publique ; fournisseurs tiers (OpenAI, OpenRouter, Gemini, custom). - Clés d'API stockées de façon sécurisée dans le Gestionnaire d'identifiants Windows via keyring (jamais en clair dans config.json). - Tests : 44 tests verts (stepper, profils, clients IA, credentials, catalogue de modèles, moteur).
This commit is contained in:
@@ -1,132 +1,101 @@
|
||||
# ai-typewriter
|
||||
# AI-Typewriter
|
||||
|
||||
Application Python qui lit la dernière entrée texte du presse-papier avec un raccourci global, l'envoie à un modèle IA, puis remplace chaque pression de touche suivante par le caractère suivant de la réponse.
|
||||
Application Python qui tourne **en arrière-plan** (icône dans la zone de notification de Windows, aucune fenêtre au démarrage), lit le contenu du presse-papier sur un raccourci global, l'envoie à un modèle IA, puis réécrit la réponse **caractère par caractère** à chaque pression de touche physique.
|
||||
|
||||
Un profil spécialisé « Mathématiques (LaTeX) » marque les équations avec `[EQ]...[/EQ]` : l'application les intercepte et déclenche `Alt+=` pour ouvrir une équation (Word/OneNote) et `→` pour en sortir.
|
||||
|
||||
## Fonctionnement
|
||||
|
||||
1. L'utilisateur copie manuellement le texte à envoyer à l'IA.
|
||||
1. L'utilisateur copie le texte à envoyer à l'IA.
|
||||
2. Raccourci global par défaut : `Ctrl+Alt+A`.
|
||||
3. L'application lit directement la dernière entrée du presse-papier, sans simuler `Ctrl+C`.
|
||||
4. Le texte capturé est journalisé puis envoyé à Ollama ou Gemini.
|
||||
5. Le temps de génération de la réponse est journalisé.
|
||||
6. Quand la réponse arrive, le mode dactylographie s'active.
|
||||
7. Chaque touche physique appuyée est interceptée et remplacée par le prochain caractère de la réponse IA.
|
||||
8. Le hook clavier est libéré automatiquement après le dernier caractère.
|
||||
|
||||
L'application n'interprète pas les équations et ne lance pas `Alt+=`. Elle écrit uniquement le texte généré, caractère par caractère. Pour les maths, le modèle peut produire du LaTeX encadré par des marqueurs `[EQ]...[/EQ]`, puis la gestion Word peut être faite ailleurs.
|
||||
3. L'application lit le presse-papier et envoie au modèle du profil actif.
|
||||
4. Une icône reste disponible dans la zone de notification : elle permet d'ouvrir les journaux, d'ajouter/commuter des profils et de gérer les clés d'API.
|
||||
5. Chaque touche physique appuyée ensuite écrit l'élément suivant de la réponse (caractère ou séquence d'équation).
|
||||
6. Le hook clavier est libéré automatiquement à la fin de la réponse.
|
||||
|
||||
## Installation depuis les sources
|
||||
|
||||
```bash
|
||||
python -m venv .venv
|
||||
. .venv/bin/activate
|
||||
. .venv/bin/activate # Windows : .venv\Scripts\activate
|
||||
pip install -r requirements.txt
|
||||
cp config.json.template config.json
|
||||
pip install -e .
|
||||
python main.py
|
||||
```
|
||||
|
||||
Sous Linux, le paquet `keyboard` nécessite souvent les droits root ou l'accès aux périphériques `/dev/input`. Sous Windows, lancez l'exécutable dans une session utilisateur normale.
|
||||
À la première exécution, l'application crée son fichier de configuration :
|
||||
`%APPDATA%\ai-typewriter\config.json` (Linux : `~/.config/ai-typewriter/config.json`).
|
||||
|
||||
## Configuration
|
||||
## Configuration (profils)
|
||||
|
||||
Copiez `config.json.template` vers `config.json` puis adaptez :
|
||||
La configuration contient une liste de **profils** nommés et le profil actif. Chaque profil décrit :
|
||||
|
||||
```json
|
||||
{
|
||||
"provider": "ollama",
|
||||
"model": "llama3.1",
|
||||
"api_key": "",
|
||||
"server_url": "http://localhost:11434",
|
||||
"hotkey": "ctrl+alt+a",
|
||||
"request_timeout_seconds": 300,
|
||||
"math_text_format": "plain"
|
||||
}
|
||||
```
|
||||
| Champ | Description |
|
||||
|---|---|
|
||||
| `name` | Libellé affiché dans les menus |
|
||||
| `provider` | `ollama`, `openai`, `openrouter`, `gemini`, `custom` (OpenAI-compatible) |
|
||||
| `model` | Nom du modèle (choisissable via le sélecteur) |
|
||||
| `server_url` | Base de l'instance (ex. `http://localhost:11434`) |
|
||||
| `credential` | Nom logique de la clé d'API (voir « Authentification ») |
|
||||
| `system_prompt` | Instructions données au modèle |
|
||||
| `equation_enabled` | Active l'interception des marqueurs d'équation |
|
||||
| `eq_start_marker` / `eq_end_marker` | Marqueurs (défaut `[EQ]` / `[/EQ]`) |
|
||||
| `eq_start_key` / `eq_end_key` | Touches déclenchées (défaut `alt+=` / `right`) |
|
||||
|
||||
### Ollama
|
||||
Deux profils sont créés par défaut : **Général** et **Mathématiques (LaTeX)**.
|
||||
|
||||
```json
|
||||
{
|
||||
"provider": "ollama",
|
||||
"model": "llama3.1",
|
||||
"server_url": "http://localhost:11434"
|
||||
}
|
||||
```
|
||||
### Profil Mathématiques (LaTeX)
|
||||
|
||||
### Gemini
|
||||
|
||||
```json
|
||||
{
|
||||
"provider": "gemini",
|
||||
"model": "gemini-1.5-flash",
|
||||
"api_key": "VOTRE_CLE",
|
||||
"server_url": "https://generativelanguage.googleapis.com"
|
||||
}
|
||||
```
|
||||
|
||||
### Timeout IA
|
||||
|
||||
`request_timeout_seconds` vaut `300` par défaut. Si Ollama charge un gros modèle ou répond lentement, augmentez cette valeur. Mettez `0` pour désactiver le timeout côté application.
|
||||
|
||||
### Configuration maths LaTeX
|
||||
|
||||
Pour laisser le modèle générer du LaTeX tout en indiquant clairement les débuts/fins d'équations :
|
||||
|
||||
```bash
|
||||
cp config.math-latex.template config.json
|
||||
```
|
||||
|
||||
Cette config garde :
|
||||
|
||||
```json
|
||||
"math_text_format": "plain"
|
||||
```
|
||||
|
||||
Donc l'application ne transforme rien. Elle tape littéralement la réponse reçue, caractère par caractère.
|
||||
|
||||
Exemple de réponse demandée au modèle :
|
||||
Le prompt système demande au modèle de produire du LaTeX encadré par `[EQ]...[/EQ]`, par exemple :
|
||||
|
||||
```text
|
||||
Les racines sont [EQ]z_1 = x + iy[/EQ] et [EQ]z_2 = x - iy[/EQ].
|
||||
```
|
||||
|
||||
Pour les fractions, intégrales, sommes, etc., le modèle peut utiliser du LaTeX standard dans les balises :
|
||||
À chaque `[EQ]` l'application envoie `Alt+=` (ouvre une équation inline), tape le LaTeX littéralement, puis envoie `→` à chaque `[/EQ]`. Ce comportement est désactivé par défaut sur les autres profils (le texte est tapé tel quel).
|
||||
|
||||
```text
|
||||
On obtient [EQ]\frac{a+b}{c+d}[/EQ] puis [EQ]\int_0^1 f(x)\,dx[/EQ].
|
||||
```
|
||||
## Zone de notification (icône)
|
||||
|
||||
Modes disponibles :
|
||||
L'application se lance sans fenêtre visible. Le menu de l'icône propose :
|
||||
|
||||
- `plain` : mode recommandé ; injecte la réponse exactement telle que le modèle l'a renvoyée.
|
||||
- `unicode` : ancien mode texte Unicode (`z_1` → `z₁`, `x^2` → `x²`) sans objet équation.
|
||||
- **Ouvrir les logs** — fenêtre des journaux en temps réel (également écrits dans `%APPDATA%\ai-typewriter\logs\app.log`).
|
||||
- **Ajouter un profil** — formulaire (nom, fournisseur, modèle, serveur, prompt, équations).
|
||||
- **Modifier le profil** — sous-menu listant tous les profils pour choisir le profil actif.
|
||||
- **Gérer l'authentification** — enregistrer les clés d'API des fournisseurs.
|
||||
- **Quitter** — arrête le processus.
|
||||
|
||||
## Compilation
|
||||
### Sélection et téléchargement des modèles
|
||||
|
||||
### Windows
|
||||
Dans le formulaire de profil, « Choisir / télécharger… » ouvre un sélecteur qui :
|
||||
|
||||
Après clonage du dépôt, lancez simplement :
|
||||
- liste automatiquement les modèles déjà disponibles localement (Ollama `/api/tags`) ;
|
||||
- si connecté à Internet, permet de rechercher dans la bibliothèque publique d'Ollama, de vérifier un modèle exact et de lancer son téléchargement (`ollama pull`).
|
||||
|
||||
### Authentification des fournisseurs
|
||||
|
||||
Les clés d'API ne sont **jamais écrites** dans le fichier de configuration. Chaque profil référence une clé par un nom logique ; la clé est stockée de façon sécurisée dans le **Gestionnaire d'identifiants de Windows** (via `keyring`). Le menu **Gérer l'authentification** permet de les enregistrer, vérifier ou supprimer.
|
||||
|
||||
## Compilation (Windows)
|
||||
|
||||
```bat
|
||||
build.bat
|
||||
```
|
||||
|
||||
Le script crée `.venv`, installe les dépendances, nettoie les anciens artefacts puis génère un exécutable Windows autonome :
|
||||
Le script crée `.venv`, installe les dépendances, puis produit un exécutable autonome **sans console** dans `dist\ai-typewriter.exe`. Il tourne directement en zone de notification.
|
||||
|
||||
```text
|
||||
dist\ai-typewriter.exe
|
||||
```
|
||||
|
||||
### Commande PyInstaller équivalente
|
||||
## Test rapide sans hook clavier ni icône
|
||||
|
||||
```bash
|
||||
pyinstaller --onefile --paths src --name ai-typewriter.exe main.py
|
||||
python main.py --debug --ask "Résume: bonjour tout le monde"
|
||||
```
|
||||
|
||||
L'exécutable est généré dans `dist/`. Le binaire n'est pas versionné Git.
|
||||
Envoie le prompt au profil actif et imprime la réponse brute (aucune icône ni interception clavier).
|
||||
|
||||
## Test rapide sans hook clavier
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
python main.py --config config.json --ask "Résume: bonjour tout le monde"
|
||||
. .venv/bin/activate
|
||||
pytest
|
||||
```
|
||||
|
||||
La suite couvre le découpage en actions (caractères/équations), le stepper, le dépôt de profils, les clients IA (Ollama/Gemini/OpenAI), le stockage sécurisé (keyring mocké) et le catalogue de modèles — sans réel hook clavier, réseau ni Gestionnaire d'identifiants.
|
||||
Reference in New Issue
Block a user