# 🧠 Console IA — PROMPT / Brief de travail

> Ce document est le « prompt » de référence du projet **oai.by-cyberdev.com**.
> Il sert à **reprendre le travail** à tout moment : objectif, choix techniques,
> état d'avancement, prochaines étapes. Charge-le dans ton assistant pour resynchroniser.

> 🌐 **CIBLE PRODUCTION :** `https://oai.by-cyberdev.com` — FastAPI + Passenger
> (O2Switch) + console web de chat, **déployée et en production**.

---

## 🎯 Objectif

Une **console IA web self-hosted** qui agrège des **modèles de langage gratuits**,
avec **persistance des discussions et des projets**, un **menu latéral** complet,
un **rendu Markdown** avec containers de code + bouton « Copier », et un **partage**
par lien public.

Les modèles sont répartis en **deux catégories** :

1. **⚡ SANS clé à saisir** (mis en avant) : le serveur utilise son **propre pool
   de clés** (variable d'env). L'utilisateur clique sur un modèle → ça discute, zéro config.
2. **🔑 AVEC clé (API EXT)** : les fournisseurs qui demandent une clé sont **groupés**
   dans un **menu déroulant** + un **champ `API EXT`** pour saisir sa clé.
   Bouton *Tester* (valide la clé + mesure la latence) et *Enregistrer* (stocke la
   clé chiffrée côté serveur).

Connexion : **OAuth (Google / GitHub / GitLab)** + mot de passe (admin).
Usage : perso ou toute personne ayant accès.

---

## 🎨 Design & fonctionnalités (décidés avec l'utilisateur)

- **Console web complète** (HTML/JS + API FastAPI), pas seulement du Swagger
  (Swagger quand même activé sur `/docs`).
- **Menu latéral gauche** :
  - boutons **« Nouvelle discussion »**, **« Nouveau projet »** (gabarit/paramètres),
    **`⚙️ Paramètres des recherches`**, et **`Historique des discussions`**.
  - liste des **projets** et des **discussions**, chacune avec actions
    **Modifier / Partager / Corbeille** (mini-boutons visibles aussi sur mobile).
  - **`Quota utilisateur`** (barre de progression) + bouton login.
- **Rendu Markdown** : `markdown-it.min.js` + `highlight.min.js` (thème Github).
  Chaque bloc de code est un **container** avec l'en-tête du langage (ou du nom de
  fichier détecté) et un bouton **« 📋 Copier »** (avec repli `execCommand`).
- **Partage** : lien public en lecture seule généré par le serveur
  (`/v1/projects/{id}/share`, `/v1/discussions/{id}/share`) + page de consultation
  (`/share/{token}`, `/project/{token}`).
- **Drag & drop** de pièces jointes dans le composeur (zone élargie, robuste).
- **Modes** : 🪞 Réflexion, 🔎 Recherche, 🎓 Experts, 💻 code — activables par
  bouton ; à l'activation d'un mode sans service choisi, un **modèle adapté est
  suggéré automatiquement** (`suggestForMode`).
- **Paramètres de recherches** persistés en `localStorage` : langue, catégories
  prioritaires, recherche web — injectés dans le system prompt (`buildSystem`).
- **Barre de progression par fournisseur** dans la barre d'outils + quota
  utilisateur (endpoint `/v1/usage`).
- **Responsive mobile** : la sidebar passe en bandeau haut, mini-boutons visibles.
- **Streaming SSE** : backend envoie `data: {"delta": "..."}` / `{"done": true}` /
  `{"error": ...}` ; le front parse via `parseSSE()` (avec repli texte brut et
  formats OpenAI).

---

## ⚙️ Choix & contraintes techniques

| Sujet | Décision |
|-------|----------|
| Framework | FastAPI + uvicorn (local), Passenger/a2wsgi (O2Switch) |
| Prod URL | `https://oai.by-cyberdev.com` (déployé) |
| Base de données | **MySQL `viwi1623_oai`** (user `viwi1623_oai`) ; **repli fichier JSON** `app/data/store.json` si indispo |
| Tables MySQL | `users`, `user_keys`, `chat_logs`, `oauth_states`, `projects`, `discussions`, `messages`, `sessions` |
| Sessions | **stockées en MySQL** (table `sessions`) pour être partagées entre les processus Passenger (l'in-memory causait des 401 intermittents « Non connecté ») ; repli RAM |
| Auth console | OAuth (Google/GitHub/GitLab) + username/mot de passe (`AUTH_PASSWORD`) → cookie `oai_session` |
| Stockage des clés EXT | Chiffrées (XOR sur hash de `AUTH_SECRET`) en MySQL ou fichier |
| Client HTTP | `requests` (timeout 60 s), API compatible OpenAI pour tous les providers |
| Local port | **8081** (8080 pris par Voice_Clone) |
| Catalogue | Catégorie `no_key` (pool serveur OpenRouter `:free`/quasi-gratuit) + `user_key` (API EXT) |

---

## 🗂️ Arborescence

```
oai_console/
├── main.py                  # App FastAPI complète (auth, chat, projets, discussions, partage, quota, SSE)
├── passenger_wsgi.py        # Pont O2Switch (ASGIMiddleware/a2wsgi)
├── requirements.txt
├── .env / .env.example / .env.prod   # secrets + BDD
├── README.md                # doc d'usage
├── PROMPT.md                # ce document
├── deploy_o2switch.sh       # déploiement O2Switch
└── app/
    ├── providers.py         # registre fournisseurs (NO_KEY / USER_KEY)
    ├── oauth.py             # flux OAuth Google/GitHub/GitLab
    ├── catalog_scan.py      # scan/construction du catalogue
    ├── templates/index.html # console web (sidebar, markdown, modes, drag&drop)
    ├── static/              # markdown-it.min.js, highlight.min.js, github.min.css
    ├── data/                # (gitignoré) repli store + clés + catalogue
    └── logs/
```

---

## 🔌 Points d'entrée principaux

### Front & auth
| Endpoint | Rôle |
|----------|------|
| `GET /` | Console web (index.html) |
| `GET /docs` / `/redoc` | Swagger / Redoc |
| `GET /v1/health` | Santé (MySQL, OpenRouter) |
| `GET /v1/me` | Session courante |
| `POST /v1/login` / `/v1/register` / `/v1/logout` | Auth mot de passe |
| `GET /v1/auth/{provider}/login` / `/callback` | OAuth (google, github, gitlab) |

### Projets & discussions (persistance)
| Endpoint | Rôle |
|----------|------|
| `GET/POST /v1/projects` | Lister / créer un projet |
| `PUT/DELETE /v1/projects/{id}` | Modifier / supprimer un projet |
| `POST/DELETE /v1/projects/{id}/share` | Activer / supprimer le partage d'un projet |
| `GET/POST /v1/discussions` | Lister / créer une discussion |
| `GET/PUT/DELETE /v1/discussions/{id}` | Lire / renommer / supprimer |
| `GET/POST /v1/discussions/{id}/messages` | Lire / publier les messages |
| `PUT/DELETE /v1/discussions/{id}/messages/...` | Modifier / supprimer un message |
| `POST/DELETE /v1/discussions/{id}/share` | Partager une discussion |
| `GET /v1/share/{token}` / `/v1/share/project/{token}` | Lecture d'un lien partagé (JSON) |
| `GET /share/{token}` / `/project/{token}` | Pages publiques de partage |

### Chat & fournisseurs
| Endpoint | Rôle |
|----------|------|
| `POST /v1/chat` | Chat (réponse complète) |
| `POST /v1/chat/stream` | Chat **SSE** (`{"delta":...}` / `{"done":true}` / `{"error":...}`) |
| `GET /v1/catalog` | Fournisseurs par catégorie |
| `POST /v1/keys` / `/v1/keys/delete` | Sauver / supprimer une clé EXT |
| `POST /v1/providers/test` | Tester une clé + latence |
| `GET /v1/providers/status` | Statut des fournisseurs |
| `GET /v1/usage` | Quota utilisateur + usage par fournisseur |

---

## ✅ État d'avancement

### Déployé en production et validé
- **Sessions MySQL multi-process** : login → `/v1/me` → création de discussion et
  de projet fiables entre processus Passenger (corrige les 401 intermittents « Non connecté »).
- **Menu latéral** : nouvelles discussions / nouveaux projets / historique renommer-
  partager-corbeille ; **création, modification et partage de projet** validés en prod.
- **Streaming SSE corrigé** (le front « affichait `{"delta":...}` en vrac ») :
  backend `data: {"delta":...}` parsé par `parseSSE()`.
- **Rendu Markdown + containers de code + boutons Copier** servis depuis `/static`.
- **OAuth state + mojibé UTF-8** corrigés.
- Connexions aux services : catégorie `no_key` (OpenRouter pool serveur, modèles
  gratuits : deepseek-v4-flash, nemotron-reasoning, minimax, glm-5.2, gemma-4, ling…)
  et `user_key` (API EXT) opérationnelles.

### Fait localement (à l'utilisateur / agent), déployé
- `suggestForMode` (auto-sélection d'un modèle adapté en activant un mode)
- Drag & drop robuste (zone élargie), `copyCode` avec repli
- CSS barre progression provider + quota, responsive mobile (mini-boutons visibles)
- Paramètres de recherches persistés (langue, catégories) injectés dans `buildSystem`

### À faire / à surveiller
- **Idéalement** vérifier visuellement le responsive et le drag & drop sur mobile
  (pas de test navigateur headless fiable sur ce Mac — s'appuyer sur les tests prod HTTP).
- Éventuellement **grouper par fichier** en mode code : aujourd'hui 1 container par
  bloc + nom de fichier détecté en en-tête ; un vrai groupage multi-blocs reste optionnel.
- Vérifier la **latence** par fournisseur et le comportement du **pool serveur**.

---

## ⚠️ Pièges / rappels

- **Passenger = WSGI, FastAPI = ASGI** → `a2wsgi.ASGIMiddleware(app)` obligatoire
  et **stdout/stderr capturés à l'import** (sinon « Incomplete response »).
- **Sessions en mémoire = 401 intermittents** multi-process → **toujours MySQL**
  (table `sessions`) ; le repli RAM reste uniquement pour assurer la continuité.
- **Le Python local bloque au démarrage** (≈/.pythonrc ou site-packages) : valider
  la syntaxe avec `/usr/bin/python3 -S` (ast), pas `python3` nu.
- **`node` n'est pas sur le PATH du shell** : utiliser `/usr/local/bin/node` pour
  valider le JS des `<script>` (via `vm.Script`).
- Le `.env` de prod contient des caractères `(` `%` dans le MDP MySQL → **ne pas
  `source` le .env** ; extraire via `grep "^VAR=" .env | cut -d= -f2-`.
- **Ne jamais mettre les vraies clés dans le front** ni dans un commit.
- Port local **8081** (8080 occupé par Voice_Clone).
- Après tout changement : `touch tmp/restart.txt` puis re-tester login → projets →
  discussion → `POST /v1/chat/stream` avec le **même cookie** (`curl -c/-b`).
