3. Les Librairies Partagées (echo_libs)
Le répertoire 14-owui-libs/ regroupe les modules Python partagés par l'ensemble
du framework : Filtres, Pipe, Actions et Admin Manager les importent tous. Cette centralisation
garantit un point de vérité unique pour chaque mécanisme critique — authentification, persistance,
communication API, interface HUD — et prévient toute duplication de code.
💡 Rôle des ECHO Libs
Ces modules constituent le système nerveux d'ECHO. Ils ne contiennent pas de logique métier (c'est le rôle du Pipe et des Filtres), mais fournissent les primitives fondamentales : comment stocker un message, comment appeler l'API Gemini, comment gérer un token OAuth2, comment injecter une interface dans le DOM d'Open WebUI.
echo_constants.py — Constantes et Topologie (v5.6)
Registre unique de toutes les vérités immuables du système. Tout composant qui a besoin d'un identifiant de modèle, d'un chemin de répertoire, d'un timeout ou d'une limite de tokens doit le lire depuis ce fichier — jamais le coder en dur localement.
Identifiants de modèles Gemini
| Constante ECHO | Nom AI Studio | Nom API Antigravity | Usage |
|---|---|---|---|
MODEL_PRO |
gemini-3.1-pro-preview |
gemini-pro-agent |
Expertise — dernier recours uniquement |
MODEL_FLASH |
gemini-3.5-flash |
gemini-3-flash-agent |
Moteur agentique principal |
MODEL_LITE |
gemini-3.1-flash-lite |
gemini-3.1-flash-lite |
Réflexe — point d'entrée par défaut |
MODEL_DISTILLATION |
gemini-2.5-flash |
gemini-2.5-flash |
Moulage et distillation de fichiers |
MODEL_EMBEDDING |
BAAI/bge-m3 |
— | Vectorisation locale (Embedding Worker) |
Paramètres de génération
| Constante | Valeur | Rôle |
|---|---|---|
MAX_TOKENS_DEFAULT | 65 535 | Limite universelle (AI Studio + API Antigravity). 65 536 provoque une erreur 400 sur Gemini 3.1 Pro et Lite API Antigravity. |
THINKING_LEVEL_PRO | "HIGH" | Réflexion maximale pour MODEL_PRO. |
THINKING_LEVEL_FLASH | "HIGH" | Réflexion standard pour MODEL_FLASH. |
THINKING_LEVEL_LITE | "HIGH" | Confirmé fonctionnel avec HIGH sur l'API Antigravity. |
THINKING_LEVEL_TOOLS | "MINIMAL" | Outils stateless (maps, grounding, distillation rapide). |
TEMP_DEFAULT | 1,0 | Température de génération principale. |
TOP_P_DEFAULT | 0,90 | Nucleus sampling. |
ECHO_RETRY_BASE_DELAY | 5.0 (augmenté de 2.0 en v5.166.6) | Base du backoff exponentiel (base × jitter × 2^attempt). Augmenté pour absorber les 400 transiants du gateway Code Assist lors de rafales (ex: consult_council). 4 essais couvrent ~62s de fenêtre de throttle. |
§1.4 ECHO Codex — Constantes
Section ajoutée en v5.4. Centralise tous les paramètres de l'éditeur Codex.
| Constante | Type | Description |
|---|---|---|
CODEX_DIR_NAME | str | Nom du sous-dossier Codex dans le Vault ("codex"). |
CODEX_LANG_MAP | dict | Mapping extension → identifiant Monaco Editor (30+ langages). Exemple : .py → "python", .ts → "typescript". |
CODEX_DEFAULT_LANG | str | Fallback si l'extension est inconnue ("plaintext"). |
CODEX_EDIT_SYSTEM_PROMPT | str | System prompt injecté dans le sub-chat d'édition AI. Impose le retour du fichier complet modifié, sans explication ni Markdown enveloppant. |
CODEX_SUMMARIZE_PROMPT | str | Prompt pour la distillation d'un fichier. Structure en 5 sections : objectif, architecture, dépendances, patterns, dette technique. |
CODEX_QUICK_ACTIONS | dict | 8 actions rapides prédéfinies (shorter, longer, comment, uncomment, refactor, fix, tests, optimize) affichées comme boutons dans le HUD Monaco. |
§1.5 DELEGATE SUB-AGENT — Blacklist et Appendice Système
Section ajoutée en v5.6. Centralise les règles de filtrage des outils transmis au sous-agent.
| Constante | Type | Description |
|---|---|---|
DELEGATE_SUBAGENT_BLACKLIST |
frozenset |
Ensemble des noms de fonctions interdites au sous-agent. 4 catégories d'exclusion : • Récursion : delegate_to_subagent (guard depth=1 absolu)• Écriture RAG : save_memory, forget_memory, save_session_context• Rendu UI : generate_rich_visualization• Méta-session : list_subagent_sessions, close_subagent_session, summarize_subagent_session, context_gauge
|
DELEGATE_SYSTEM_APPENDIX |
str |
Bloc de règles injecté automatiquement à la fin du system_prompt de chaque sous-agent. Substitutions : {sub_sid} et {max_calls}. Définit le SESSION_ID, le budget d'appels, le protocole QUESTION: et la séquentialité obligatoire des outils. |
Détection MIME (get_gemini_mime)
La fonction get_gemini_mime(file_path) retourne le tuple (mime_type, est_supporté_gemini)
en suivant une cascade de six niveaux :
- Mappings pré-définis ECHO (
MIME_MAPPING_TXT,MIME_MAPPING_BIN) — priorité absolue. - Bibliothèque standard Python
mimetypes(extension). - Détection binaire par Magic Numbers via
filetype. - Liste blanche native Gemini (
image/*,video/*,audio/*,text/*,application/pdf,application/json). - Épreuve textuelle (Null-Byte Sniffing) : si aucun
\x00dans les 1024 premiers octets →text/plain. - Fallback sécuritaire :
application/octet-stream, non supporté.
echo_utils.py — Cœur Réactif (v7.21)
EchoStateManager — Persistance Bit-Perfect
La classe EchoStateManager est l'organe de mémoire persistante. Elle gère
les bases SQLite en mode WAL (Write-Ahead Logging) pour la résistance aux pannes.
Deux instances coexistent dans chaque tour de traitement :
state_manager: lie à la base de chat{chat_id}.db— Ombres, Suture, Signatures, Journal.identity_manager: lie àidentity.db— Authentification, Quotas, Configuration utilisateur.
⚙️ Double hachage SHA-256 (Merkle Core)
Invariant Hash : SHA-256(role + content_sorted + tool_io)
— identité pure d'un tour, indépendante de sa position dans l'historique.
Cumulative Hash : SHA-256(invariant_hash + parent_cumulative_hash)
— ADN de la conversation. Toute modification dans l'historique invalide les hashes suivants.
Ce mécanisme permet de détecter les Ghost Messages (messages modifiés dans Open WebUI) et de basculer en Cold Recovery sans corrompre les tours non modifiés.
EchoGeminiClient — Moteur d'Appel API
EchoGeminiClient est le sélecteur de protocole symétrique :
il gère de manière transparente les deux backends d'inférence selon la méthode d'authentification
disponible pour l'utilisateur.
| Protocole | Authentification | URL de base | Modèles |
|---|---|---|---|
| AI Studio | Clé API AIza… |
generativelanguage.googleapis.com/v1beta |
Noms canoniques ECHO (gemini-3.5-flash, etc.) |
| API Antigravity | OAuth2 Bearer (token) | cloudcode-pa.googleapis.com/v1internal |
IDs internes Antigravity (gemini-3-flash-agent, etc.) |
⚙️ Stratégie de résilience — Failover Hybride
-
Erreurs 429/500/503 (surcharge) : backoff exponentiel avec jitter aléatoire
(
ECHO_RETRY_BASE_DELAY × jitter × 2^attempt). AprèsKEY_SWITCH_THRESHOLD(2) erreurs consécutives sur la même source, bascule sur la source suivante dans le registre des fournisseurs. - Erreurs 403/404 (droits / modèle indisponible) : bascule immédiate vers la source suivante, sans délai.
-
Transparence : chaque tentative et chaque bascule est signalée
en temps réel via
EchoEvents.status()dans l'interface Open WebUI.
v7.15 — Crédits OAuth2 opt-in
Le champ enabled_credit_types dans les requêtes API Antigravity est désormais
omis par défaut (alignement sur le comportement natif d'AGY-IDE).
Sans ce champ, le serveur utilise les quotas gratuits sans consommer de crédits payants Google One AI.
L'activation est possible via la UserValve ENABLE_PAID_CREDITS du Pipe,
propagée via __metadata__ et persistée dans echo_settings.
⚙️ Status tri-état (v7.20)
Toutes les réponses d'outils utilisent désormais un status à trois états explicites :
"success"— exécution nominale, modèle utilisé = modèle demandé."warning"— exécution réussie mais avec divergence (clamping politique ou cascade). Le champreasondétaille la cause."error"— échec de l'exécution (cascade épuisée, exception, config invalide).
Le champ clamped:true est supprimé : la divergence modèle est signalée
uniquement via status=warning + champ reason.
Fonctions utilitaires et protocole Multipart
| Fonction | Rôle |
|---|---|
split_thought_process(text) | Isole le contenu des balises <think> / <thought> du texte final. Retourne (texte_propre, pensées). |
wrap_tool_output(text, status, multiparts, nouveaux_fichiers) | Construit le dictionnaire multipart standardisé retourné par chaque outil au Pipe. Status par défaut : {"status": "success"}. |
wrap_cascade_output(text, model_requested, model_used, status, reason) | Enrichit wrap_tool_output avec les métadonnées de cascade. Si model_used ≠ model_requested, le status passe en warning et le champ reason explique la divergence. Le modèle effectif est également préfixé dans le texte. |
get_echo_version() | Lit la version depuis /app/backend/data/ECHO_VERSION (copié depuis le fichier VERSION du dépôt). |
index_text_in_ephemeral_rag() | Pipeline complet chunk → embed → upsert Qdrant pour le RAG éphémère. Recouvrement inter-chunks pour préserver le contexte aux jointures. |
Politique Modèle Centralisée — clamp_model() et resolve_model_policy()
Ces deux fonctions constituent le verrou de politique entre le Pipe et
les outils. Elles garantissent que tout outil respecte la MODEL_SELECTION
définie par l'utilisateur.
| Fonction | Rôle |
|---|---|
resolve_model_policy(metadata, user_id) |
Résout la politique active depuis __metadata__ (canal Pipe). Fallback
SQLite via EchoStateManager.get_setting("model_policy") si absent.
Retourne (mode, plafond_key) : ("auto", "MODEL_FLASH"),
("auto_pro", "MODEL_PRO") ou ("fixed", "MODEL_XXX"). |
clamp_model(requested, metadata, user_id) |
Applique la politique sur un modèle demandé par un outil. En mode
fixed, retourne toujours le modèle fixé. En mode auto,
retourne min(demanded, plafond) via MODEL_HIERARCHY. |
call_cascade() — Appel LLM centralisé avec cascade
Méthode statique de EchoGeminiClient. Point d'entrée unique recommandé
pour tous les outils qui appellent un LLM. Elle gère de façon transparente :
- Clamping — applique
clamp_model()avant l'appel. - Injection
thinkingConfig— niveau adapté au modèle (PRO/FLASH/LITE). - Cascade descendante — si le modèle est indisponible (429/503), repli automatique PRO → FLASH → LITE avec toast et status émis.
- Crédits opt-in —
enable_paid_creditspropagé via__metadata__.
call_cascade()data, model_key, reason = await EchoGeminiClient.call_cascade(
target_model_key="MODEL_FLASH", # Clé logique (sera clampée par la politique Pipe)
payload=payload,
user_id=user_id,
metadata=__metadata__,
events=events,
include_thoughts=False, # True pour agents (préserve thoughtSignatures)
)
# data : dictionnaire de réponse API Gemini (None si cascade épuisée)
# model_key : clé ECHO du modèle effectivement utilisé
# reason : None (nominal) ou chaîne expliquant la divergence ("policy", "API error", …)
Table echo_settings — Persistance inter-sessions
Table SQLite dans identity.db (gérée par EchoStateManager).
Elle stocke les préférences Pipe (model_policy,
enable_paid_credits) pour que les outils puissent les lire même quand
OWUI ne leur propage pas __metadata__.
| Méthode | Rôle |
|---|---|
save_setting(key, value) | Écrit une clé dans echo_settings (identity.db). |
get_setting(key) | Lit une clé depuis echo_settings. Retourne None si absente. |
Table codex_docs — Registre Codex (v7.21)
Table SQLite ajoutée dans {chat_id}.db pour le suivi des fichiers ECHO Codex.
Elle permet l'injection dans le vecteur proprioceptif (registre_codex)
et des statistiques rapides sans accès disque.
| Méthode | Rôle |
|---|---|
save_codex_record(filename, language, lines, last_commit, commit_msg) | INSERT OR UPDATE dans codex_docs. Appelé après chaque commit Codex. |
delete_codex_record(filename) | Supprime une entrée du registre (appelé lors de la suppression d'un fichier). |
get_codex_docs() | Retourne tous les fichiers Codex du chat (pour injection dans registre_codex par le Filtre). |
clear_codex_records() | Purge intégrale du registre (appelé par l'action Reset du HUD). |
echo_auth.py — Identités d'Accès aux Modèles (v7.3)
AuthService gère le cycle complet d'authentification OAuth2 headless via le flux
Authorization Code + PKCE (RFC 7636). Ce choix permet à ECHO de s'authentifier
avec un compte Google depuis un conteneur Docker sans navigateur ni intervention humaine répétée.
Flux PKCE — séquence d'authentification
initiate_pkce_flow(): génère le code verifier + challenge, ouvre un tunnel SSH éphémère (asyncssh) sur un port dynamique de la plage8020–8024, et renvoie l'URL d'autorisation Google à l'utilisateur.- L'utilisateur clique sur le lien, autorise ECHO sur son compte Google.
await_pkce_callback(): tâche asyncio en arrière-plan qui attend le callback Google sur le port interne (8025–8034) via le tunnel SSH.- Le code d'autorisation est échangé contre un
access_tokenet unrefresh_token, stockés dansidentity.db.
⚙️ Rafraîchissement proactif des tokens
EchoAuth.refresh_google_oauth_token() vérifie proactivement si le token a plus
de 3 300 secondes (55 minutes).
Si c'est le cas, il demande silencieusement un nouveau token via refresh_token
et l'enregistre dans identity.db. Ce processus est complètement transparent
pour l'utilisateur.
Méthodes de quota API Antigravity (v7.x)
| Méthode | Rôle |
|---|---|
fetch_available_models() | Appel :fetchAvailableModels (API Antigravity). Parse le quotaInfo de chaque modèle et stocke dans google_quota_by_model (JSON dict dans identity.db). |
fetch_user_quota() | Appel :loadCodeAssist mode HEALTH_CHECK. Extrait les crédits disponibles depuis paidTier.availableCredits. |
get_model_quota(ca_model_id) | Lecture du quotaInfo spécifique à un modèle CA depuis identity.db. Fallback {} si modèle inconnu. Utilisé par le HUD. |
refresh_quota_if_needed() | Déclenche fetch_available_models() de manière asynchrone non-bloquante si les données ont plus de 10 minutes. Ne bloque jamais la génération. |
echo_protocol.py — Adaptateur API Antigravity (v1.1)
Module de fonctions pures (sans état, sans appel réseau) : point de modification
unique pour adapter les requêtes ECHO au format de l'API Antigravity interne.
Il centralise la traduction des identifiants de modèles et la normalisation de
generationConfig.
get_ca_model_id(echo_model)
Traduit un nom de modèle canonique ECHO (AI Studio) vers l'ID interne API Antigravity.
La correspondance est définie dans MODEL_MAP_CA (source de vérité dans
echo_constants.py).
Note : le préfixe _ca_ dans les noms de fonctions est l'abréviation interne
de « cloudcode-pa API » et est conservé tel quel dans le code source.
| Nom ECHO (AI Studio) | ID API Antigravity |
|---|---|
gemini-3.1-pro-preview | gemini-pro-agent |
gemini-3.5-flash | gemini-3-flash-agent |
gemini-3.1-flash-lite | gemini-3.1-flash-lite (identique) |
gemini-2.5-flash | gemini-2.5-flash (identique) |
build_ca_generation_config(raw_gen_conf)
Normalise le generationConfig pour le backend API Antigravity v1internal :
-
Cap
maxOutputTokensà 65 535 — décision D1 : alignement sur le modèle le plus restrictif (Gemini 3.1 Pro AGY). -
thinkingConfigpasse intégralement —includeThoughts: trueest requis pour que l'API Antigravity retourne les partsthought: truelisibles dans le stream (balises<think>). Sans ce champ, seule lathoughtSignatureopaque est retournée. -
response_mime_typeaccepté — confirmé fonctionnel sur tous les modèles AGY.
✅ Champ CA_EXCLUDED_GEN_CONF_FIELDS
Actuellement un frozenset vide : tous les champs du generationConfig
passent intégralement vers l'API Antigravity. Ce point de contrôle centralisé permet d'exclure
rapidement un champ devenu incompatible sans modifier le code du Pipe.
echo_skills.py — Gestionnaire de Compétences (v1.3)
Ce module gère la lecture et l'écriture des fichiers SKILL.md dans le Vault utilisateur
(répertoire skills/). Il centralise l'extraction du frontmatter YAML (nom, description)
et du contenu de la compétence, utilisés par la fonction forge_skill des agents cognitifs.
| Fonction | Rôle |
|---|---|
get_all_skills(user_id) | Retourne la liste de toutes les compétences (métadonnées) du Vault. |
get_skill_content(user_id, skill_id) | Retourne le contenu complet (instructions) d'une compétence donnée. |
save_skill(user_id, skill_id, name, desc, instructions) | Génère ou met à jour le fichier SKILL.md avec le bon formatage YAML. |
echo_ui.py / echo_visuals.py — Interface HUD
echo_ui.py (v5.20) et echo_visuals.py forment le moteur d'injection
dynamique de l'interface HUD dans Open WebUI. Ils sont détaillés dans la section
HUD & UI.
⚙️ SQLite — Persistance par chat
Toutes les bases SQLite d'ECHO sont gérées par EchoStateManager avec
un timeout de connexion de 10 secondes pour éviter les blocages sur accès concurrent.
Deux bases coexistent par utilisateur : identity.db (auth, quotas) et
{chat_id}.db (ombres, sutures, signatures cognitives).