Sur écran large, la fin de la conversation était recouverte par la carte de
saisie et aucun défilement ne la ramenait : le fil réservait 8 px sous lui
là où le composeur en occupe ~160.
styles.css réservait bien la hauteur (#chat{padding-bottom:170px}), mais deux
règles POSTÉRIEURES dans la feuille — ajoutées par le redesign « Terre » puis
par le correctif de largeur de lecture — réécrivaient `padding` en raccourci
sous @media (min-width:721px), ce qui remet padding-bottom à la valeur du
raccourci. Sous 721 px la règle en raccourci est déclarée AVANT, d'où un bug
invisible sur mobile. Ces règles passent en longhands (padding-top +
padding-inline), et un commentaire dit pourquoi le raccourci est proscrit ici.
La réserve devient mesurée au lieu d'être devinée : syncComposer() publie
--composer-h (hauteur réelle du composeur) via un ResizeObserver, à côté de
syncGutter() qui fait déjà ce travail pour --sbw. Une constante redevenait
fausse dès que la saisie grandit ou qu'une pièce jointe s'affiche. Le
scrollbtn suit la même variable. env(safe-area-inset-bottom) disparaît du
calcul : il est déjà dans la hauteur mesurée, le compter deux fois creusait
un trou en PWA iOS.
Le voile de fondu au-dessus de la carte s'exprimait en % de la hauteur TOTALE
du composeur : l'opacité pleine tombait sous le bord haut de la carte, et le
texte restait lisible au ras du bord — l'impression de « passer derrière ».
Une variable --fade pilote désormais la bande réservée ET la course du
dégradé, qui devient donc opaque exactement au bord de la carte.
Mesuré au navigateur, du 380 px au 2000 px, au repos / saisie 10 lignes /
pièce jointe en attente : écart de 46 à 52 px partout. En réinjectant
l'ancienne règle : -119 px, bug reproduit. La largeur de lecture est
inchangée (1080 px de contenu à 2000 px de fenêtre).
Barre latérale : la discussion sélectionnée porte un cadre sauge complet et
fin (1 px) au lieu d'un liseré de 3 px sur le seul bord gauche. La bordure
transparente est portée par tous les états, la sélection ne décale donc pas
le contenu.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VueWA9xcYadaYq65tBisix
Loki — assistant IA local en conteneur (fork d'AJEAN)
Loki est un fork de AJEAN de nathaninline, sous licence MIT — voir
NOTICE.mdetLICENSE. L'essentiel du code et des fonctionnalités vient d'AJEAN ; ce fork le rebaptise et le fait tourner dans un conteneur Docker GPU autonome, là où l'amont s'installe en binaire + systemd sur la machine hôte.
Loki fait tourner un modèle de langage 100 % en local : tchat, mémoire persistante, accès internet, outils MCP, agent (shell, fichiers), accès distant chiffré — serveur d'inférence llama.cpp compris, dans une seule image.
Architecture
┌────────────────── conteneur loki ──────────────────┐
│ loki web (UI + API, port 8090, premier plan) │
│ │ pilote (fichier PID — pas de systemd) │
│ loki serve ──exec──► llama-server (CUDA, :8080) │
│ ▲ modèles .gguf │
│ /data (config, bbolt, mémoire, workspace) │
│ /models (GGUF déposés à la main) │
└────────────────────────────────────────────────────┘
- Un seul conteneur : l'UI joint le moteur sur
localhost(contrainte héritée de l'amont), les deux partagent donc le même conteneur. - Sans systemd : l'amont pilote le moteur via systemctl ; en conteneur,
Loki bascule automatiquement sur une supervision par fichier PID
(
internal/loki/sys_service_container.go). Changer de modèle depuis l'UI redémarre le moteur normalement. - Le moteur (port 8080, non authentifié par défaut) n'est pas exposé ; seule l'UI (8090) l'est.
Démarrage rapide (Docker, GPU NVIDIA)
Pré-requis : pilote NVIDIA + NVIDIA Container Toolkit.
cp .env.example .env
docker compose up --build # quelques minutes : llama-server vient précompilé
# de l'image officielle llama.cpp (server-cuda)
Interface : http://localhost:8090 — télécharge un modèle depuis le catalogue intégré (onglet modèles), il démarre tout seul.
Installation sur Unraid
L'image est construite et publiée par GitHub Actions sur GHCR
(ghcr.io/r0m1k3/loki:latest) à chaque push sur main — aucun build sur
Unraid. Compose prêt à l'emploi : docker-compose.unraid.yml.
- Installe le plugin Nvidia Driver (Apps) et vérifie
nvidia-smi. - Crée les dossiers :
mkdir -p /mnt/user/appdata/loki/data /mnt/user/appdata/loki/models - Plugin Compose Manager → nouvelle stack → colle
docker-compose.unraid.yml→ Compose Up. - Interface :
http://<ip-unraid>:8090.
Configuration
Tout se règle dans l'UI (modèle, contexte, presets…) et survit aux
redémarrages (volume /data). Variables d'environnement du conteneur :
| Variable | Rôle | Défaut |
|---|---|---|
LOKI_WEB_PORT |
port de l'UI | 8090 |
LOKI_MODEL |
modèle initial (semé au 1er boot seulement) | — |
LOKI_CTX |
taille de contexte initiale | 32768 |
LOKI_NGL |
couches GPU initiales | 999 (tout) |
LOKI_HOME |
données (volume) | /data |
LOKI_MODEL_DIRS |
dossiers .gguf additionnels | /models |
En CLI dans le conteneur : docker exec -it loki loki status (aussi :
logs, restart, config, bench, test…).
Fonctionnalités (héritées d'AJEAN)
- Tchat avec streaming, raisonnement visible, pièces jointes, vision (selon modèle), export de conversations.
- Mémoire persistante (
memory off|ondemand|always). - Accès internet : recherche + lecture de pages, moteur Go intégré ou Crawl4AI pour les pages JS.
- Agent : shell, fichiers, workspace (
agent on). - Serveurs MCP : Node.js est inclus dans l'image pour les serveurs
npx. - Presets de configuration par modèle, bench, auto-détection GPU.
- Accès distant chiffré via le relais ajean.link (service opéré par l'auteur de l'amont).
- API OpenAI-compatible exposable (
network on, protégée par clé).
Différences avec l'amont
| AJEAN (amont) | Loki (ce fork) | |
|---|---|---|
| Installation | binaire + sudo ajean install (systemd) |
docker compose up |
| Moteur llama.cpp | compilé sur la machine (ajean llamacpp install) |
image officielle llama.cpp (server-cuda), précompilée |
| Supervision moteur | systemd / launchd / PID (Windows) | fichier PID (LOKI_CONTAINER=1) |
| Configuration initiale | ajean edit ($EDITOR) |
entrypoint + loki config set |
| Mise à jour | ajean update (binaire GitHub) |
docker compose pull |
Le reste — UI, mémoire, outils, protocole — est celui d'AJEAN. Pour récupérer les évolutions de l'amont :
git fetch upstream && git merge upstream/main # conflits de renommage à arbitrer
Build sans GPU / autres accélérateurs / version épinglée
L'image Loki se construit au-dessus de l'image serveur officielle de
llama.cpp, choisie par le build-arg LLAMACPP_IMAGE :
# CPU seul (test sans GPU)
docker build --build-arg LLAMACPP_IMAGE=ghcr.io/ggml-org/llama.cpp:server .
# Vulkan (GPU AMD/Intel/NVIDIA sans CUDA)
docker build --build-arg LLAMACPP_IMAGE=ghcr.io/ggml-org/llama.cpp:server-vulkan .
# Version de llama.cpp épinglée (reproductible)
docker build --build-arg LLAMACPP_IMAGE=ghcr.io/ggml-org/llama.cpp:server-cuda-b10423 .
Aucune compilation de llama.cpp n'a lieu : le moteur est maintenu et précompilé par l'équipe amont (toutes architectures GPU courantes).
Licence
MIT — © les contributeurs d'AJEAN (« Jean contributors ») pour le code amont,
voir LICENSE et NOTICE.md.