Deux causes indépendantes faisaient échouer le job test de la CI (et
seulement en CI : ni .env ni les mêmes ordres de chargement en local) :
- test_agent_web_tools.mock_http patche http_client.shared_client pendant
sa fenêtre d'exécution. Le premier import d'importers/url_fetch dans
cette fenêtre fige la factory moquée dans le namespace du module →
tous les appels fetch_url suivants du processus passaient par le handler
mocké de l'autre test (« assert '…/post' == '…/page' » dans
test_v56_import). url_fetch résout désormais le client à l'appel, et le
mock_http restaure la vraie factory (référence figée au chargement du
module) y compris sur url_fetch ;
- test_agent.py posait RATE_LIMIT_ENABLED=false en env var, sans effet sur
le singleton Settings déjà instancié : sous pytest -n auto, le worker
dépassait le quota de 60 req/min et 8 tests recevaient des 429
(KeyError 'id' au passage). Le fixture désactive maintenant le limiter
sur le singleton, comme les autres fichiers de tests.
- aide : bouton ✕ en haut à droite du panneau (classe partagée
settings-close, 44 px mobile) + helpInit.close() (retour en arrière,
sinon /workspaces) ; .settings-panel en position:relative pour ancrer
hamburger + ✕ au panneau
- éditeur « Insert below » (/Write with AI) : insère le markdown source
conservé à la génération (AIC._md) au lieu du texte extrait du HTML rendu
(_resultText() reste seulement en repli) → titres/listes/gras conservés
- listes numérotées : aucun numéro n'était affiché (CSS = retrait seul) ;
le rang des blocs numbered_list contigus est calculé au rendu (data-num)
et rendu via content: attr(data-num) — /numbered list et l'insertion
agent affichent 1, 2, 3
- md2b : cases à cocher - [ ] / - [x] testées avant la branche des puces
(aligné sur paste2b) + séparateur 1) accepté (CommonMark)
- menu slash : requête tapée dans le bloc (/numbered list) répercutée dans
le filtre du menu quand le focus n'a pas rejoint l'entrée
- tests : tests/test_v7592_ui_fixes.py (5 tests, dont 1 comportemental node
qui exécute le vrai md2b) ; ruff I001 préexistant sur test_agent.py
- livraison : VERSION + app/main = 7.59.2, OpenAPI 525 chemins, CHANGELOG
La clé fonctionne: /v1/models 200 + chat 200 (vérifié live). L'échec venait
du modèle: mistral-large-latest (défaut PROVIDERS + tête de liste) n'est pas
servi par les plans d'abonnement basiques → 403 code 1910 « tier_not_allowed »,
et le Test connection sélectionnait systématiquement ce premier candidat.
- PROVIDERS mistral default → mistral-small-latest (tous plans)
- PROVIDER_MODELS réordonnée: tous-plans d'abord (ordre du test de connexion)
- mistral ∈ _CHAT_VALIDATED_PROVIDERS: le fetch modèles ne garde que les
modèles réellement servis (46 listés → 25 utilisables avec la clé du compte)
- migration 36: default_model bloqué (large/pixtral-large) reset en base
Test live déployé: {ok:true, model:mistral-small-latest, reply:PONG,
verified:true} · tests/test_agent.py 53/53 · nouveau test d'ancrage
test_mistral_defaults_are_tier_safe
- A3 : helper `_require_user_id()` (401 sans session) sur profile/password/token/forge ; `PUT /api/user/password` exige `current_password` vérifié ; `/api/user` sorti de la liste CSRF exemptée
- A4 : `POST /api/v1/token` → 401 sans session, chemin legacy `user_id=0` supprimé
- A5 : CRUD membres d'espace (POST/PUT/DELETE) : session + rôle admin de l'espace (ou admin global), placeholder user créé en `is_admin=0`, GET membres sans session → 401
- A6 : `_require_view` → 404 et `_require_edit` → 401 quand il n'y a pas de session (fin du legacy single-user sur les collections)
- A7 : création ET lecture de page → 401 sans session (PermissionManager conservé) ; `/board/api/pages` sorti de `EXCLUDED_PATHS` ; header CSRF manquant ajouté sur setItemIcon (local_workspace)
- A8 : seed admin sans mot de passe codé en dur — aléatoire au premier boot loggé une fois, ou `FLOWDECK_ADMIN_PASSWORD` ; re-seed seulement si absent
- tests : client connecté par défaut via `_TestSessionAuth` (session + CSRF injectés à la volée, jamais dans le cookie jar → plus de CookieConflict), helper `anon()` sur les 40 tests d'anonymat ; 1016/1016 verts, `ruff check app tests` OK
Un api_base stocke (ex. https://api.mistral.ai/v2) ecrasait l'URL par defaut corrigee et faisait echouer le test de connexion. Desormais: normalisation a l'ecriture (une base egale au defaut n'est pas stockee), possibilite de vider le champ (api_base='' vs None), et migration 14 qui efface les bases obsoletes/redondantes dans user_llm_keys et llm_config.
Tests de non-regression ajoutes.
Cohere -> /compatibility/v1, Google Gemini -> /v1beta/openai, Perplexity -> host racine, Chutes -> llm.chutes.ai/v1, SenseNova -> compatible-mode/v1. Mise a jour des modeles par defaut (xAI grok-4.6, Fireworks deepseek-v4-pro-0813, Cohere command-a-plus).
Retrait de LTX Studio (aucune API chat-completions) et MemTensor/MemOS (API memoire non OpenAI-compatible, auth Token + /chat). Google utilise desormais l'auth Bearer pour lister les modeles. Test de non-regression ajoute.
- LLMClient : default_model scope par provider — tester nvidia alors que deepseek est le provider actif ne lui envoie plus 'deepseek-v4-flash' (cause du 404 'model not found' de NVIDIA)
- presets NVIDIA actualises (anciens modeles retires de la plateforme / premium)
- test de regression ajoute (46 passed)
- /api/agent/mentions : reponse en sections (fichiers de l'espace courant ouvert, collections, pages de collections, autres documents), workspace_id transmis par le frontend (localWsId) et prioritaire
- Navigation clavier up/down : la liste defile pour garder la selection visible (menus @ et /)
- Deduplication des propositions (meme type + meme titre affiches une seule fois)
- Skills : plus d'injection du texte du skill dans la boite d'edition; requete composee en arriere-plan (contexte + skills + texte) a l'envoi; les skills integres injectent leur template, les enregistres partent via skill_ids
- Tests : shape des mentions, dedup, scoping workspace
- Les skills (menu /, integres et enregistres) s'epinglent comme des bulles dans le composer, au meme titre que les mentions @; plusieurs peuvent coexister sur un meme post
- L'API /run accepte skill_ids (tableau) et l'engine injecte tous leurs prompts dans le system prompt (skill_id conserve pour retro-compat)
- Clic sur une bulle de contexte (@ document/page/base) ouvre l'element comme document courant (/pages/<id> ou /db/<id>); le bouton x retire sans ouvrir
- Envoi possible avec des skills seuls sans texte
- test_engine_multiple_skills_applied
- L'engine envoie le message assistant avec ses tool_calls (id) et chaque resultat d'outil avec son tool_call_id, y compris en cas de refus; la passe suivante n'est plus refusee par l'API
- Un fournisseur reel configure qui echoue remonte maintenant une erreur (SSE error) au lieu de repeter la question via le mock hors-ligne (mock reserve a offline/sans cle)
- llm_client conserve id + arguments_raw des tool_calls
- test de regression test_engine_tool_protocol_messages
- Composeur contenteditable : mentions inline (pastilles icône+nom), barre de contexte groupée documents/skills, sélecteur @ (icône+titre+chemin), skills intégrés + agent_skills + commandes admin via '/'
- Actions sous chaque réponse agent : copier, insérer dans la page, feedback 👍/👎
- Backend : table agent_feedback, GET /api/agent/mentions, POST /api/agent/feedback, contexte document:<id>/page:<id>/collection:<id> résolu en contenu réel
- Inclut le travail v4.14.0 (documents/espace de travail + outils + auto-titre de conversation)