Manuel Utilisateur Complet — Phases 1→14 + P2 + P3 + V8 FINAL

AutomationSequence
V8.0

Plateforme d'automatisation Python avancée — AutomationSequence.
Phases 7→14 + V8 : Architecture Plugin · Réseau/Serveur · IA/LLM · GUI V8 · Multi-machine · Sécurité avancée · Engine V2 · Tests/Deploy
~145 Actions 12 Thèmes Plugin API IA/LLM Ollama AES-256-GCM Audit HMAC Multi-machineWeb APIAssistant IAExport EXE
145+
Actions
12
Thèmes
15
Modules
~12k
Lignes
200+
Tests
100%
Compat V6
01

Introduction V8.0

Qu'est-ce que AutomationSequence V8 ?

AutomationSequence est une plateforme d'automatisation de bureau Python, développée par Tristan Ruard. Elle permet de créer, éditer et exécuter des séquences d'actions automatisées — clics, saisies, lectures de fichiers, requêtes réseau, OCR, IA — sans écrire de code.

La V8 est une évolution de la V7.0, ajoutant nettoyage complet + nouvelles fonctionnalités (éditeur visuel, marketplace plugins, multi-séquence). 100% rétrocompatible avec toutes les séquences JSON V5, V6 et V7.

Nouveautés V8 vs V7

Phase 7 — Architecture Plugin : extensibilité sans modifier le code source
Phase 8 — Réseau : SFTP, SSH, LDAP/AD, IMAP, HL7, TCP (20 actions)
Phase 9 — IA/LLM : Ollama local, OpenAI, classification, OCR++, vision
Phase 10 — GUI V7 : Command Palette, SmartForm, Bibliothèque, Débogueur V2
Phase 11 — Multi-machine : agents distants, variables partagées réseau
Phase 12 — Sécurité avancée : vault AES-256, audit HMAC immuable
Phase 13 — Engine V2 : checkpoint/resume, profiler, async/await
Phase 14 — Tests & Deploy : pytest, PyInstaller, build.bat

Principes de fonctionnement

Une séquence est un tableau JSON d'actions. Chaque action est un objet avec un champ type et des paramètres spécifiques. Le moteur les exécute séquentiellement dans un thread séparé.

Les variables ($VAR{NOM}) permettent de passer des données entre actions. Elles sont typées (string, int, float, bool, list, dict) et résolubles dans tous les paramètres.

Les séquences JSON sont sauvegardées et rechargées à volonté. Format identique V5/V6/V7/V8.

Architecture V8

main.py — Interface tkinter V8 (GUI, Command Palette, Bibliothèque, Canvas Editor)
engine.py — Moteur V8 (checkpoint, profiler, async, 32 workers)
actions.py — 101 actions V6 (Phases 1-6)
network_actions.py — Actions réseau Phase 8
ai_actions.py — Actions IA/LLM Phase 9
agent_client.py — Actions multi-machine Phase 11
plugin_api.py — Système de plugins Phase 7
vault_v2.py + audit.py — Sécurité Phase 12

02

Installation

Prérequis système

Python 3.10+ (recommandé : 3.11 ou 3.12) — Windows 10/11 64-bit
Tesseract OCR (optionnel, pour les actions OCR) : https://github.com/UB-Mannheim/tesseract/wiki
Ollama (optionnel, pour les actions IA en mode offline) : https://ollama.ai

Installation minimale (core V6 + GUI V7)
pip install pyautogui pygetwindow pyperclip requests
pip install Pillow pynput psutil openpyxl
pip install cryptography schedule pystray
pip install pytesseract pyttsx3
Installation complète (toutes les phases V7)
pip install -r requirements.txt
pip install paramiko # Phase 8 — SSH/SFTP
pip install ldap3 # Phase 8 — LDAP/AD
pip install pytest # Phase 14 — Tests
Tesseract OCR doit être installé séparément (binaire Windows). Chemin par défaut : C:\Program Files\Tesseract-OCR\tesseract.exe. Cocher les langues "fra" et "eng" lors de l'installation.
💡
Pour les actions IA en mode 100% offline (conformité sécurité), installer Ollama puis : ollama pull llama3 (texte) et ollama pull llava (vision). Aucune donnée ne quitte le réseau local.
03

Interface V8

🗂 Zones principales

Topbar — Logo, version, fichier courant, statut d'exécution
Toolbar — Boutons Play/Stop/Step/Record, paramètres d'exécution
Log — Journal en temps réel (vert = OK, rouge = KO)
Panneaux latéraux — Bibliothèque (gauche) et Débogueur (droite)
Notebook central — Onglets : Séquence, Variables, Vault, Dashboard, Historique, Paramètres, À Propos, Plugins

📋 Onglet Séquence

Liste des actions avec indentation visuelle (If/ForEach/Macro).
Barre de recherche filtrante, multi-sélection Ctrl/Shift, Drag & Drop.
Menu contextuel clic droit : Éditer, Dupliquer, Monter/Descendre, Supprimer.
Bouton ➕ Ajouter → ouvre la Command Palette.

🔌 Onglet Plugins (V8)

Liste Treeview de tous les plugins installés avec statut, version, auteur, actions déclarées.
Actions : Activer, Désactiver, Hot-reload (sans redémarrer), Installer depuis ZIP, Ouvrir dossier plugins.
Double-clic → détail complet du plugin.

04

Raccourcis Clavier

RaccourciActionNouveauté
Ctrl+PCommand Palette — recherche parmi toutes les actionsV8 ★
Ctrl+BAfficher/masquer la Bibliothèque de séquencesV8 ★
F5Jouer la séquence (= bouton ▶ JOUER)V8 ★
F6Arrêter l'exécution (= bouton ⏹ STOP)V8 ★
Ctrl+SSauvegarder la séquence (JSON)V6
Ctrl+OCharger une séquence (JSON)V6
Ctrl+ZUndo (pile de 50 états)V6
Ctrl+YRedoV6
Ctrl+DDupliquer la sélectionV6
Ctrl+ASélectionner toutes les actionsV6
DelSupprimer les actions sélectionnéesV6
Ctrl+CCopier les actions sélectionnées (presse-papier interne)V8 ★
Ctrl+VColler après la sélectionV8 ★
Ctrl+TOuvrir un fichier dans un nouvel ongletV8 ★
Ctrl+WFermer l'onglet courantV8 ★
F2 / Double-clicOuvrir SmartFormDialog (éditeur)V8 ★
Bouton ▶⤵ Depuis NDémarrer depuis l'action sélectionnée (ignorer 1→N-1)V8 ★
05

Command Palette V8

Présentation

La Command Palette (Ctrl+P) est une fenêtre de recherche rapide à la VS Code. Elle permet d'ajouter n'importe quelle action à la séquence en 2 frappes de touches sans parcourir de menus.

Tapez quelques lettres pour filtrer en temps réel parmi les 145+ types d'actions. Naviguez avec ↑↓, validez avec Entrée.

L'action sélectionnée ouvre automatiquement le SmartFormDialog pré-rempli avec les valeurs par défaut.

Exemple — rechercher "sftp"
Ctrl+P → taper "sftp"

Résultats filtrés :
📂 SFTP Envoyer fichier (SFTPPut)
📂 SFTP Télécharger fichier (SFTPGet)
📂 SFTP Lister répertoire (SFTPList)
📂 SFTP Supprimer fichier (SFTPDelete)
📂 SFTP Créer répertoire (SFTPMkdir)

↵ Entrée → SmartFormDialog SFTPPut
💡
La palette fonctionne aussi avec des mots-clés en français : "réseau", "mail", "image", "boucle", "condition", etc.
06

SmartFormDialog V8

Formulaires dynamiques auto-générés

En V7, chaque type d'action a son propre formulaire de saisie avec des champs typés (entry, int, bool, combo, text, file, password). Fini l'édition JSON brute pour les utilisateurs non-techniques.

Le SmartFormDialog s'ouvre via F2, double-clic sur une action, ou depuis la Command Palette. Il montre les paramètres pertinents pour chaque type avec des libellés clairs en français.

Bascule Vue JSON

La case "Vue JSON" en haut du formulaire permet de basculer vers l'éditeur JSON brut à tout moment. Le JSON est synchronisé avec le formulaire à la bascule.

Les utilisateurs avancés peuvent éditer directement en JSON ; les débutants utilisent uniquement les champs visuels. Les deux modes produisent le même résultat.

La validation s'effectue au clic "✅ Appliquer" — un message d'erreur s'affiche si le JSON est malformé.

07

Bibliothèque de Séquences V8

Parcours de dossiers

Le panneau gauche masquable (Ctrl+B) liste tous les fichiers JSON du dossier courant. Cliquer "📂 Dossier" pour naviguer vers n'importe quel répertoire. Double-clic = charger la séquence immédiatement.

Favoris

Clic droit → "⭐ Ajouter aux favoris" pour épingler une séquence. Les favoris sont persistants (seq_favorites.json). Cliquer "⭐ Favoris" pour n'afficher que les favoris.

Aperçu au survol

Survoler une entrée 600ms affiche un tooltip avec les 15 premières actions de la séquence (type + description). Idéal pour retrouver rapidement la bonne séquence sans l'ouvrir.

08

Débogueur V2 V8

Variable Inspector

Le panneau droit (bouton 🔬 dans la toolbar) affiche en temps réel toutes les variables avec leur type Python et leur valeur actuelle. Les variables dont la valeur vient de changer s'affichent en orange. Double-clic sur une variable → l'ajoute à la Watch list.

Watch List

Listez les variables critiques à surveiller. Chaque variable surveille ses changements indépendamment. Del pour retirer une variable de la liste. Les valeurs changées s'affichent en orange.

Évaluation live

L'onglet "⚡ Eval" permet d'évaluer n'importe quelle expression $VAR{} pendant l'exécution en pause (mode Step). Pratique pour vérifier les calculs ou explorer les variables complexes (listes, dicts).

Exemples d'évaluation
$VAR{NB_LIGNES} → 42
$VAR{NOM}_$VAR{PRENOM} → DUPONT_Jean
résultat : $VAR{RESULT} → résultat : OK
09

12 Thèmes

Cyber Navy

Original V6 — bleu nuit profond

V6
Dracula

Violet/rose, fond sombre classique

V6
Monokai Pro

Jaune/orange, fond prune

V6
Nord

Bleu arctique, palette douce

V6
Solarized Dark

Palette Solarized officielle

V6
Arctic Light

Thème clair, bleu glacier

V6
Thème Officiel

Thème bleu institutionnel

V6
High Contrast

Noir total, accessibilité maximale

V6
Tokyo Night ★

Bleu/cyan, fonds sombres profonds

V7/V8
Catppuccin Mocha ★

Mauve pastel, tons froids

V7/V8
Gruvbox Dark ★

Jaune warm, tons boisés

V7/V8
One Dark Pro ★

Standard Atom/VS Code

V7/V8
💡
Changer le thème depuis l'onglet Paramètres → Thèmes. L'application se reconstruit instantanément. Le choix est sauvegardé dans prefs.json. Recherchez un thème par son nom dans la barre de filtrage.
10

Variables $VAR{}

Syntaxe et types

Toute valeur de paramètre peut contenir $VAR{NOM} qui sera résolu avant exécution. Les variables sont typées :

TypeExemplesAction SetVariable
string"Bonjour", ""varType: "string"
int42, -5varType: "int"
float3.14, -0.5varType: "float"
booltrue, falsevarType: "bool"
list["a","b","c"]varType: "list"
dict{"k":"v"}varType: "dict"
Opérations List & Dict

Liste : ListAppend (ajouter), ListGet (lire par index), ListLength (longueur)
Dict : DictSet (écrire clé), DictGet (lire clé)

Résolution imbriquée
Texte = "Dossier $VAR{DATE}_$VAR{ID_DOSSIER}"
→ "Dossier 20260402_654321"

Une liste en JSON string :
$VAR{MA_LISTE} → ["a","b","c"]

Un dict en JSON string :
$VAR{MON_DICT} → {"nom":""}
11

If / Else / EndIf — 13 opérateurs

OpérateurDescriptionExempleVersion
==Égalité stricteifVar=STATUS, ifValue=OKV5
!=DifférenceifVar=CODE, ifValue=0V5
contientSous-chaîneifVar=MSG, ifValue=ERREURV5
est videValeur vide ou espacesifVar=RESULTATV5
> < >= <=Comparaison numériqueifVar=SCORE, ifOp=">", ifValue=80V6
regexExpression régulièreifVar=ID_DOSSIER, ifValue="^\d{6}$"V6
exprExpression arithmétique sécuriséeifValue="$VAR{A}*2 > 100"V6
startswithCommence parifVar=NOM, ifValue="Dr."V8 ★
endswithTermine parifVar=FICHIER, ifValue=".pdf"V8 ★
12

Boucles & ForEach

WhileLoop / EndWhile V8

Boucle tant que la condition est vraie. La condition est réévaluée à chaque passage.

{"type":"WhileLoop","condition":"$VAR{N} > 0"}
...actions...
{"type":"DecrementVar","varName":"N","step":1}
{"type":"EndWhile"}

⚠️ Toujours prévoir une sortie (DecrementVar, Break ou Stop) pour éviter les boucles infinies. Utilisez Break pour sortir prématurément, Continue pour passer à l'itération suivante.

RepeatBlock

Répète un bloc N fois. repeatCount peut contenir $VAR{}.

{"type":"RepeatBlock","repeatCount":5}
...actions...
{"type":"EndRepeat"}
ForEach — 3 sources

list : variable liste Python
csv : fichier CSV → dict par ligne
range : entiers de/à/pas

{"type":"ForEach","forVar":"ITEM",
 "forSource":"range",
 "forFrom":1,"forTo":10,"forStep":1}
Goto Label

Sauts conditionnels avec Label + GotoLabel. Utile pour les boucles conditionnelles complexes ou les retries manuels.

{"type":"Label","labelName":"RETRY"}
...actions...
{"type":"GotoLabel","labelName":"RETRY"}
13

Macros & CallSequence

DefineMacro / CallMacro

Une macro est un bloc d'actions réutilisable avec paramètres. Définie dans la même séquence, appelable plusieurs fois avec des paramètres différents.

{"type":"DefineMacro","macroName":"CONNEXION"},
{"type":"FocusWindow","windowTitle":"$VAR{APP}"},
{"type":"TypeTextClipboard","text":"$VAR{LOGIN}"},
{"type":"EndMacro"},
{"type":"CallMacro","macroName":"CONNEXION",
"macroParams":{"APP":"MonApp","LOGIN":"user"}}
CallSequence V8 — Scope isolé

En V8, CallSequence supporte scope=local pour isoler les variables de la sous-séquence. Le returnVar permet de récupérer un résultat dans le scope parent.

{"type":"CallSequence",
"seqPath":"sous-seq.json",
"scope":"local",
"returnVar":"SOUS_RESULT",
"inputVars":{"PARAM":"valeur"}}
💡
scope="shared" (défaut) = comportement V6. scope="local" = variables isolées, idéal pour les sous-séquences réutilisables.
14

Parallélisme — 32 workers

ParallelBlock V8

En V8, maxWorkers peut aller jusqu'à 32 (V6 : 4). Chaque worker est tracé individuellement dans le log avec son index [W1], [W2]... et sa durée. Le profiler mesure chaque worker séparément si activé.

{"type":"ParallelBlock","maxWorkers":8}
{"type":"SFTPPut","host":"srv1",...},
{"type":"SFTPPut","host":"srv2",...},
{"type":"SSHCommand","host":"srv3",...}
{"type":"EndParallel"}
Bonnes pratiques

Les actions dans un ParallelBlock partagent le même VariableStore. Éviter d'écrire dans la même variable depuis plusieurs workers simultanément.

Pour des opérations indépendantes (envoyer des fichiers vers plusieurs serveurs, pinger plusieurs hôtes), le parallélisme est idéal.

Le ParallelBlock est synchrone : la séquence attend que tous les workers soient terminés avant de passer à l'action suivante.

15

AsyncAction / AwaitAsync V8

Lancer une action en arrière-plan

AsyncAction démarre une action dans un thread séparé et ne bloque pas la séquence. La séquence continue immédiatement à l'action suivante. L'action est identifiée par un asyncId unique.

// Lance SSHCommand sans attendre
{"type":"AsyncAction","asyncId":"SSH1",
"action":{"type":"SSHCommand","host":"srv",
  "command":"backup.sh","varStdout":"SSH_OUT"}},
// ... d'autres actions pendant ce temps ...
{"type":"Delay","duration":2000},
// Récupérer le résultat quand nécessaire
{"type":"AwaitAsync","asyncId":"SSH1",
"varOk":"SSH_OK","varMsg":"SSH_MSG","timeout":120}
AwaitAsync — récupération

AwaitAsync bloque jusqu'à ce que l'action async identifiée par asyncId soit terminée, ou jusqu'au timeout (secondes).

varOk reçoit "true" ou "false". varMsg reçoit le message de résultat.

Si le timeout est atteint, varOk="false" et varMsg="timeout_Ns". L'action async est annulée.

Les actions async partagent le même VariableStore. Utiliser des asyncId et des noms de variables distincts pour chaque action async simultanée.
16

Checkpoint / Resume V8

Principe

Le moteur V8 peut sauvegarder périodiquement son état (action courante + toutes les variables) dans checkpoint.json. En cas de crash, coupure de courant ou fermeture accidentelle, il est possible de reprendre exactement là où la séquence s'était arrêtée.

Idéal pour les séquences longues nocturnes traitant des centaines de dossiers.

Activation depuis main.py ou code
# Activer le checkpoint toutes les 10 actions
engine.checkpoint_enabled = True
engine.checkpoint_interval = 10

# Reprendre après un crash
if engine.has_checkpoint():
  info = engine.get_checkpoint_info()
  print(f"Reprendre depuis l'action {info['idx']+1}")
  engine.resume_from_checkpoint()
💡
Le fichier checkpoint.json est supprimé automatiquement à la fin normale d'une séquence. Il ne persiste qu'en cas d'interruption anormale.
17

Profiler Intégré V8

Mesure de performance par action

Le profiler mesure la durée d'exécution de chaque action. À la fin, un rapport s'affiche dans le log avec le Top 10 des actions les plus lentes.

Utile pour identifier les bottlenecks OCR, les WaitForImage trop longs, les requêtes réseau lentes, etc.

Activation et export
# Activer depuis le code
engine.profiler_enabled = True

# Après exécution — rapport dans le log :
# ==========================================
# PROFILER — 42 actions — total : 8420ms
# Top 10 actions les plus lentes :
# WaitForImage 2340ms (27.8%)
# ReadTextOnScreen 1180ms (14.0%)
# ==========================================

# Export CSV
engine.export_profiler_report("perf.csv")
18

Souris, Clavier & Fenêtres

TypeDescriptionParamètres clés
LeftClick / RightClick / DoubleClick / MiddleClickClic à une positionx, y
MoveMouse / MouseSmoothDéplacer le curseurx, y (smooth: steps)
ClickAndDragCliquer-glisserx, y → x2, y2
ScrollWheelMolettex, y, amount
MouseHoverSurvol (sans clic)x, y, duration
ClickRegionClic centre d'une régionx, y, w, h
KeyPressTouche simplekey (VK_CODE)
KeyComboCombinaison Ctrl/Shift/Alt/Winkey, ctrl, shift, alt, win
TypeTextSaisie rapidetext ($VAR{} ok)
TypeTextClipboardSaisie via presse-papierstext ($VAR{} ok)
FocusWindow / CloseWindow / MaximizeWindow / MinimizeWindowGestion fenêtreswindowTitle (partiel)
WaitForWindowAttendre l'ouverture d'une fenêtrewindowTitle, timeout
LaunchAppLancer une applicationappPath, args
KillProcessTuer un processusprocessName
19

Données, Fichiers & Web

CatégorieActions
ChaînesStringReplace, StringSplit, StringJoin, StringFormat, RegexExtract, HashString, Base64Encode/Decode
Fichiers texteReadTextFile, WriteTextFile (append), FileCopy, FileMove, FileDelete, FileExists, ListFiles
CSV / ExcelReadCSV, WriteCSV, AppendCSV, ReadExcel, WriteExcel
JSON / SQLiteParseJSON, SQLiteQuery (SELECT→var), SQLiteExecute (INSERT/UPDATE)
VariablesSetVariable (6 types), ListAppend/Get/Length, DictSet/Get, CounterIncrement/Reset
WebWebNavigate, HttpRequest (GET/POST/PUT/DELETE, auth Bearer/Basic/ApiKey, body JSON)
SystèmeRunShell (stdout→var), GetEnvVar, SetEnvVar, RunPython (ctx inline)
NotificationsSendMail (SMTP TLS), ToastNotification, LogMessage, PlaySound, TextToSpeech
MoteurDelay, SleepUntil, PauseHuman, Assert, SetBreakpoint, Comment
20

OCR & Vision (Phase 6)

ActionDescriptionParamètres clés
ReadTextOnScreenOCR d'une région d'écran → variablex, y, w, h, lang, varName, preprocess
ClickOnTextOCR + clic au centre du texte détectétext, x, y, w, h, lang, ignoreCase
WaitForTextOnScreenPolling OCR jusqu'à détection du textetext, timeout, lang, varName
ExtractTextFromImageOCR sur fichier image/PDF → variablepath, lang, varName, extractRegex
WaitForImageAttendre l'apparition d'une image templateimagePath, confidence, timeout
ClickOnImageClic sur une image template détectéeimagePath, confidence
ScreenshotCapture écran → fichierpath, x, y, w, h
AssertPixelColorVérifier la couleur d'un pixelx, y, color (RRGGBB), varName
Les actions OCR nécessitent Tesseract OCR installé séparément. lang="fra" pour le français, lang="fra+eng" pour les deux. Le prétraitement PIL (niveaux de gris + contraste) est activé par défaut (preprocess=true).
21

Actions Réseau Phase 8 V8

SFTP / SSH (paramiko)
ActionDescription
SFTPPutEnvoyer un fichier local vers serveur SFTP
SFTPGetTélécharger un fichier depuis serveur SFTP
SFTPListLister un répertoire distant → variable liste
SFTPDeleteSupprimer un fichier distant
SFTPMkdirCréer un répertoire distant
SSHCommandExécuter une commande → stdout/stderr/RC
SSHUpload / SSHDownloadAlias SFTP via SSH
Authentification par mot de passe ou clé SSH (keyPath). Les mots de passe sont résolubles via $VAR{} ou Vault.
HL7 / TCP
ActionDescription
HL7SendEnvoyer message HL7 v2 via MLLP → ACK
HL7ParseMessageParser HL7 → dict de segments
TCPSendEnvoyer données TCP brut → réponse
PingHostVérifier l'accessibilité d'un hôte (TCP)
LDAP / Active Directory
ActionDescription
LDAPSearchRecherche LDAP → liste de dicts
LDAPModifyModifier un attribut LDAP
ADCheckGroupVérifier appartenance à un groupe AD
ADGetUserInfoRécupérer infos complètes d'un user AD
IMAP (messagerie)
ActionDescription
IMAPSearchChercher emails → liste d'IDs
IMAPReadLastLire le dernier email → sujet/corps/from
IMAPGetAttachmentTélécharger une pièce jointe
IMAPMarkReadMarquer des emails comme lus
22

Actions IA / LLM Phase 9 V8

Backends supportés

Ollama local (recommandé) — 100% offline, offline sécurisé :
ollama pull llama3 (texte) · ollama pull llava (vision)
Aucune donnée ne quitte le réseau.

OpenAI API — GPT-4o-mini (texte), GPT-4o (vision)
Requiert une clé API. Déconseillé pour les données personnelles.

Azure OpenAI — Déploiement privé Azure hébergé en France.

Configuration dans prefs.json section "ai" ou paramètre provider par action. La détection auto choisit Ollama si disponible, sinon OpenAI.

ActionDescription
LLMPromptPrompt libre → variable réponse
LLMClassifyClasser un texte parmi N catégories
LLMSummarizeRésumé (ton : neutre/technique/administratif)
LLMExtractFieldsExtraction JSON structurée (ID_DOSSIER, NomContact...)
LLMOCRCorrectCorrection post-OCR par LLM
ImageAnalyzeVision IA (screenshot/fichier) → description
LLMSelfHealAuto-correction d'action échouée → suggestion JSON
Ne jamais envoyer de données personnelles identifiantes vers les APIs OpenAI ou Azure sans validation DPO préalable. Utiliser Ollama local pour tout traitement de données sensibles.
23

Multi-machine Phase 11 V8

Déploiement d'un agent

Déployer agent_server.py sur chaque poste distant (avec Python + dépendances). L'agent expose une API REST locale.

# Sur le poste distant
python agent_server.py --port 9876 --token SECRET
# Options :
# --readonly → lecture seule (pas d'exécution)
# --host 0.0.0.0 → toutes interfaces
# --port 9876 → port HTTP
Actions disponibles
ActionDescription
RemoteRunActionExécuter une action sur un agent
RemoteRunSequenceEnvoyer + exécuter une séquence
RemoteStopArrêter la séquence d'un agent
AgentStatusÉtat, uptime, stats d'un agent
AgentGetVar / AgentSetVarLire/écrire une variable distante
Variables partagées réseau

Les actions SharedVar* utilisent un fichier JSON sur un partage réseau (lecteur mappé, UNC) pour synchroniser des données entre plusieurs instances AutomationSequence.

Le verrou fichier (cross-process) garantit la cohérence en cas d'accès simultané depuis plusieurs postes.

ActionDescription
SharedVarGetLire une variable partagée
SharedVarSetÉcrire avec lock fichier
SharedVarLockAcquérir/libérer un verrou nommé
Exemple — incrément global cross-machine
{"type":"SharedVarLock","sharedFile":"Z:/shared.json",
"lockName":"COMPTEUR","action":"acquire"},
{"type":"SharedVarGet","sharedFile":"Z:/shared.json",
"key":"COMPTEUR","varName":"C","default":"0"},
{"type":"CounterIncrement","varName":"C","step":1},
{"type":"SharedVarSet","sharedFile":"Z:/shared.json",
"key":"COMPTEUR","value":"$VAR{C}"},
{"type":"SharedVarLock","sharedFile":"Z:/shared.json",
"lockName":"COMPTEUR","action":"release"}
24

Vault — Secrets chiffrés

VaultStore / VaultGet (V6 Fernet)

Les actions VaultStore et VaultGet fonctionnent de façon identique à la V6 (Fernet AES-128). Le vault est stocké dans .vault.enc avec la clé dans .vault.key.

Ces actions sont recommandées pour les mots de passe SMTP, LDAP, tokens API dans les séquences JSON. Les valeurs ne sont jamais stockées en clair.

Règle de sécurité absolue

Ne JAMAIS versionner (Git) les fichiers :
.vault.key · .vault.enc · .vault_v2.key · .vault_v2.enc · .audit.key

Si .vault.key est perdu, les secrets sont irrécupérables. Sauvegarder la clé dans un gestionnaire de secrets externe (ex : KeePass).

25

Vault V2 — AES-256-GCM V8

Améliorations cryptographiques

Le vault V2 (vault_v2.py) remplace Fernet AES-128 par AES-256-GCM avec dérivation de clé PBKDF2-SHA256 (100 000 itérations).

Chaque secret est chiffré avec un sel aléatoire de 16 bytes et un nonce GCM de 12 bytes — impossible de déduire une clé à partir des données chiffrées même avec deux secrets identiques.

Le tag GCM 128 bits détecte toute altération du vault (intégrité authentifiée).

Migration V6 → V8 (une seule fois)
# Dans un terminal Python dans le dossier V8
from vault_v2 import migrate_vault_v6_to_v7
migre, erreurs = migrate_vault_v6_to_v7()
print(f"{migre} secrets migrés, {erreurs} erreurs")

# Les anciens .vault.key et .vault.enc sont conservés
# Les actions VaultGet/VaultStore V6 restent compatibles
Rotation de clé
from vault_v2 import get_vault_v2
vault = get_vault_v2()
vault.rotate_key() # Re-chiffre tous les secrets
# Ancienne clé sauvée en .vault_v2.key.bak.YYYYMMDDHHMMSS
26

Journal d'Audit HMAC V8

Journal immuable HMAC-SHA256

Chaque entrée de audit.log signe l'entrée précédente via HMAC-SHA256. Toute modification (suppression, altération) rompt la chaîne et est détectable via audit.verify().

Catégories : SEQUENCE, ACTION, VAULT, PLUGIN, NETWORK, AUTH, SECURITY, SYSTEM.

Rotation automatique au-delà de 1MB → archive .gz horodatée.

Masquage automatique des données sensibles (password, token, key, secret) — conformité RGPD Art. 32.

Vérification d'intégrité
from audit import get_audit
audit = get_audit()
ok, msg, nb = audit.verify()
print(f"Intégrité : {'✓' if ok else '✗'}")
print(f"{nb} entrées vérifiées")
print(msg)

# Export rapport texte
audit.export_report("rapport_audit_2026.txt", last=500)
Ne jamais supprimer .audit.key. Sans cette clé, il est impossible de vérifier l'intégrité des anciens logs. Sauvegarder avec les clés vault.
27

Architecture Plugin V8

Structure d'un plugin
plugins/
mon_plugin/
__init__.py ← vide
plugin.py ← classe BasePlugin
manifest.json ← métadonnées
manifest.json minimal
{
"name": "Mon Plugin",
"version": "1.0.0",
"author": "Tristan Ruard",
"description": "Description courte",
"actions": ["MonAction1", "MonAction2"]
}
plugin.py minimal
from plugin_api import BasePlugin, PluginManifest

class MonPlugin(BasePlugin):
  @property
  def manifest(self):
    return PluginManifest(
      name="Mon Plugin",version="1.0",
      author="",description="...",
      actions=["MonAction"])

  def run_action(self, action, runner):
    if action["type"]=="MonAction":
      val = runner.vars.get("MA_VAR")
      self.log(f"Exécuté avec val={val}")
      return True, "MonAction OK"
    return False, "Action inconnue"
Un plugin exemple complet est livré dans plugins/mon_plugin_exemple/ avec trois actions exemple : Plugin_LogID, Plugin_FormatDossier, Plugin_GetService.
28

WebhookListen V8

Déclenchement HTTP entrant

WebhookListen démarre un mini-serveur HTTP sur un port local et attend qu'un appel POST /run arrive. Le payload JSON est injecté dans les variables de la séquence.

Idéal pour déclencher AutomationSequence depuis GLPI, Nagios, un script batch, ou tout autre outil capable d'envoyer une requête HTTP.

Action WebhookListen (non-bloquant)
{"type":"WebhookListen","port":8765,"blocking":false,
"seq_path_var":"WH_SEQ","vars_prefix":"WH_"}
Appel depuis un script externe (PowerShell)
$body = @{seq_path="C:\seq.json";
       vars=@{CONTACT="DUPONT Jean"}} | ConvertTo-Json
Invoke-RestMethod -Uri "http://localhost:8765/run" `
  -Method POST -Body $body -ContentType "application/json"
29

Scheduler CRON

Type déclencheurChamp run_at / intervalExemple
oncerun_at = "YYYY-MM-DD HH:MM"Exécution unique le 2026-04-15 à 08:30
dailyrun_at = "HH:MM"Tous les jours à 07:00
hourlyinterval = N (heures)Toutes les 2 heures
minutesinterval = N (minutes)Toutes les 30 minutes
weekdayweekday = 0-6, run_at = "HH:MM"Chaque lundi (0) à 07:00
💡
Les tâches once sont désactivées automatiquement après exécution. Le thread de surveillance vérifie toutes les 10 secondes. La config est persistée dans scheduler.json et rechargée au démarrage.
30

Alertes SMTP & Toast

Configuration

Onglet Paramètres → Alertes. Configurer le serveur SMTP, les identifiants, le destinataire. Activer "Envoyer à la fin" et/ou "Envoyer en cas d'erreur".

Les notifications desktop (Toast) via plyer s'affichent en bas à droite de Windows.

Action SendMail dans la séquence

L'action SendMail permet d'envoyer un mail depuis la séquence avec un sujet et corps personnalisés via $VAR{}. Indépendante du système d'alertes automatiques.

31

Dashboard & Historique

Dashboard live

Onglet 📊 Dashboard. Compteurs OK/KO/Retry en temps réel, barre de progression, ETA, graphique de durée par action (vert=OK, rouge=KO). Rafraîchi à chaque action.

Historique SQLite

Onglet 📁 Historique. Toutes les sessions sont enregistrées dans history.db (SQLite). Filtre par statut, tri par colonne, suppression. Rétention configurable (défaut 30 jours).

Mode Record

Bouton ⏺ RECORD (pynput). Enregistre clics gauche + pressions de touches. Clic droit ou F9 = stop. Les Delay entre actions sont capturés automatiquement.

32

Tests Unitaires Phase 14 V8

Lancer tous les tests
python -m pytest tests/ -v
# Ou via le script Windows :
run_tests.bat

# Tests ciblés :
run_tests.bat variables # VariableStore
run_tests.bat engine # Engine
run_tests.bat actions # ActionRunner
run_tests.bat -v # Verbose complet
Couverture des tests

test_variables.py (~50 tests) — VariableStore : set/get, types, résolution $VAR{}, list/dict, export/import
test_engine.py (~70 tests) — Engine : SetVariable, If/Else/Endif, ForEach, Repeat, Macro, CallSequence, RunPython, hash, fichiers, SQLite, dry-run
test_actions.py (~80 tests) — ActionRunner avec mocks : strings, regex, hash, base64, fichiers, CSV, SQLite, HTTP (mock requests), Shell, Env, List/Dict, JSON

33

Build EXE Phase 14 V8

Options de build
build.bat # Complet : tests + EXE
build.bat --no-tests # EXE sans lancer les tests
build.bat --tests # Tests uniquement
build.bat --clean # Nettoyer dist\ et build_temp\
build.bat --help # Afficher l'aide

# EXE généré dans :
dist\AutomationSequence\AutomationSequence.exe
Déploiement SCCM

L'EXE PyInstaller est un dossier autonome (--onedir). Copier le dossier dist\AutomationSequence\ sur le poste cible. Python n'est pas requis sur le poste de destination.

Créer un raccourci pointant vers AutomationSequence.exe. Les fichiers de données (prefs.json, manuels HTML) sont copiés dans le même dossier.

34

FAQ V8

❓ Les séquences V6/V7 fonctionnent-elles en V8 ?

Oui, 100% rétrocompatible. Tous les fichiers JSON V5, V6 et V7 s'ouvrent et s'exécutent sans modification. Les champs V7/V8 (scope, returnVar, asyncId) sont optionnels.

❓ Comment configurer Ollama pour la Phase 9 ?

1. Télécharger Ollama : https://ollama.ai
2. ollama pull llama3 (LLM texte, ~4GB) · ollama pull llava (vision, ~4GB)
3. Vérifier : curl http://localhost:11434/api/tags
4. Dans les actions LLM : "provider":"ollama" ou laisser vide (auto-detect)

❓ Erreur "paramiko non installé"

Installer avec : pip install paramiko. Les actions SFTP et SSH nécessitent paramiko. Les autres actions réseau (IMAP, HL7, TCP) utilisent des modules Python natifs.

❓ Comment créer un plugin simple ?

Copier le dossier plugins/mon_plugin_exemple/, renommer-le, modifier manifest.json (name, actions), modifier plugin.py (class, run_action). Cliquer "🔄 Hot-reload" dans l'onglet Plugins — le plugin est disponible immédiatement sans redémarrage.

❓ Checkpoint — comment l'activer ?

Le checkpoint n'est pas activé par défaut (pour ne pas ralentir les séquences courtes). Pour les séquences longues : engine.checkpoint_enabled = True dans le code, ou via un futur paramètre dans l'onglet Paramètres → Avancé. L'intervalle par défaut est de 10 actions.

❓ L'agent distant répond "401 Unauthorized"

Le token dans l'action (agentToken) ne correspond pas au token de l'agent (--token). Vérifier la casse — le token est sensible à la casse. Utiliser $VAR{AGENT_TOKEN} résolu depuis un VaultGet pour éviter le token en clair dans le JSON.

❓ Cortex XDR réagit aux nouvelles fonctions V8

Les modules paramiko (SSH), ldap3, et requests génèrent du trafic réseau que Cortex peut analyser. Si bloqué, contacter votre administrateur système pour ajouter une exception sur python.exe dans le contexte AutomationSequence. Ces modules ne contournent pas la sécurité Windows — ils sont des clients réseau légitimes.

❓ Comment migrer le vault V6 vers V8 ?

Exécuter une seule fois : python -c "from vault_v2 import migrate_vault_v6_to_v7; print(migrate_vault_v6_to_v7())". Les anciens fichiers .vault.key et .vault.enc sont conservés. Les actions VaultGet/VaultStore dans les séquences JSON restent inchangées et utilisent toujours le vault V6. Utiliser vault_v2.py directement pour les nouveaux secrets.

36

Editeur Visuel Canvas Flowchart P2-A

Vue Canvas

Le bouton Map Canvas bascule entre la liste classique et l editeur visuel. Les actions deviennent des noeuds colores relies par des fleches. Chaque noeud affiche le type et la description courte.

Les blocs If/Else, ForEach, Repeat sont representes avec des couleurs specifiques pour visualiser la structure de flux.

Interactions

Double-clic noeud = ouvrir SmartForm.
Selection = synchronise la Listbox.
Surlignage = action en cours d execution.
Clic droit = menu contextuel Supprimer.

Couleurs des noeuds

Bleu = Controle flux (If, ForEach)
Vert = Variables
Jaune = Fichiers / CSV / Excel
Orange = Reseau / HTTP / SSH
Violet = IA / LLM
Rouge = Erreur / Breakpoint
Blanc = Systeme / Delay / Log

Canvas vs Liste

Utilisez la Liste pour ceer et editer rapidement. Utilisez le Canvas pour visualiser la logique d une sequence complexe ou la documenter. Les deux vues sont synchronisees en temps reel.

37

Marketplace de Plugins P2-B

Configurer le catalogue

Entrer l URL du fichier catalogue.json. Cliquer Actualiser pour charger la liste. Le catalogue peut etre local (file://) ou distant (https://).

Installer un plugin

1. Selectionner un plugin
2. Cliquer Installer
3. Telechargement + verification SHA-256
4. Extraction dans plugins/ + chargement a chaud

Publier un plugin

python publish_plugin.py cree un ZIP signe et met a jour le catalogue.json avec le SHA-256 et la version.

Format catalogue.json
{"plugins": [{"id": "mon_plugin", "name": "Mon Plugin", "version": "1.0.0", "author": "Auteur", "zip_url": "https://exemple.com/mon_plugin.zip", "sha256": "abc123", "actions": ["MonAction1"]}]}
37b

Canvas — Éditeur Visuel & Export P2-A

🗺 Basculer Canvas / Liste

Bouton 🗺 Canvas dans la barre de la séquence. Bascule entre la vue liste (par défaut) et la vue canvas. Le scroll et le zoom sont mémorisés lors du basculement.

La vue canvas affiche chaque action comme un nœud coloré selon sa catégorie. Les flèches montrent le flux d'exécution avec des coudes en L pour les structures imbriquées.

Codes couleurs des nœuds

Chaque catégorie d'action a sa couleur :
🟡 Or — Contrôle de flux (If, While, ForEach…)
🔵 Bleu — Variables
🟢 Vert — Souris/clics
🟣 Lavande — Clavier
🔴 Rouge — Fenêtres
🟠 Orange — OCR/écran
Gris — Système/Delay

Export du canvas

3 boutons d'export dans la toolbar du canvas :
🖼 Export PNG — capture le canvas en image PNG (nécessite Pillow)
📄 Export PDF — exporte en PDF A4 (nécessite Pillow)
📋 Export Listing — exporte la séquence en fichier texte indenté (.txt ou .md)
Avant l'export, la vue est automatiquement ajustée pour inclure tous les nœuds.

💡
L'export PNG utilise PIL.ImageGrab — aucun Ghostscript requis.
38

Multi-séquences & Persistance P2-C

Barre d'onglets V8 FINAL

Une barre d'onglets se trouve juste sous la toolbar (au-dessus de la zone Bibliothèque/Séquence). Chaque onglet est une séquence indépendante avec son propre état. Le nombre d'actions est affiché entre parenthèses : seq1.json (42).

Bouton = ouvrir un fichier dans un nouvel onglet • Bouton 🆕 Vide = onglet vierge • Bouton × = fermer • Clic onglet = basculer

Bouton Charger (Ctrl+O) — comportement intelligent

Quand l'onglet actif contient déjà des actions, Ctrl+O affiche une fenêtre de choix :
🔄 Remplacer l'onglet actif — écrase la séquence courante
➕ Ouvrir dans un nouvel onglet — ouvre le fichier à côté
Si l'onglet est vide, le fichier est chargé directement sans demande.

Copier des actions entre onglets

Méthode 1 — Tout copier : Clic droit sur onglet source → Copier toutes les actions vers l'onglet actif. Les actions sont ajoutées à la fin.

Méthode 2 — Sélection fine :
1. Aller dans l'onglet source
2. Sélectionner les actions souhaitées
3. Ctrl+C pour copier
4. Cliquer sur l'onglet cible
5. Ctrl+V pour coller

Menu clic droit sur un onglet

• 📂 Charger un fichier dans CET onglet
• ➕ Ouvrir dans un NOUVEL onglet
• 🆕 Nouvel onglet vide
• 💾 Sauvegarder
• 📋 Copier toutes les actions → onglet actif
• 📋 Copier les actions vers… (sous-menu)
• ✕ Fermer / Fermer les autres

Raccourcis onglets

Ctrl+T = ouvrir fichier dans un nouvel onglet
Ctrl+W = fermer l'onglet courant
Ctrl+C = copier la sélection (presse-papier interne)
Ctrl+V = coller après la sélection

39

Debuggeur V3 Breakpoints P2-D

Gouttière de Breakpoints

La bande grise à gauche de la liste est la gouttière. Clic gauche = poser/retirer un breakpoint (indicateur rouge ●). Clic droit = définir une condition ($VAR{X} == "valeur").

L'exécution s'arrête automatiquement sur chaque breakpoint. En mode STEP, avancez action par action avec le bouton ▶| STEP.

Breakpoints conditionnels

Un breakpoint conditionnel ne suspend l'exécution que si la condition est vraie. Exemples :
$VAR{STATUT} == "ko"
$VAR{N} > 10
$VAR{RESULT} == ""
Clic droit sur la gouttière → saisir la condition.

Panneau Inspecteur (bouton toolbar)

Bouton 📊 Inspecteur dans la toolbar = panneau latéral droit avec 3 onglets :
📦 Vars — toutes les variables, valeur en temps réel, surligné si changée
👁 Watch — variables surveillées (watchpoints), valeur et changements
⚡ Eval — évaluer une expression $VAR{} à la demande

Débogueur V3 — Fenêtre complète

Bouton 🔴 Débogueur dans Paramètres → Débogueur. Fenêtre dédiée avec 3 onglets :
🔴 Breakpoints — liste tous les breakpoints posés avec leurs conditions
👁 Watchpoints — ajouter/retirer des variables à surveiller
📦 Variables — même vue que le panneau Inspecteur

Démarrer depuis l'action N

Bouton ▶⤵ Depuis N dans la toolbar. Sélectionnez d'abord une action dans la liste, puis cliquez ce bouton. L'exécution commence à partir de cette action en ignorant toutes les actions précédentes. Utile pour reprendre après un crash ou déboguer une partie spécifique.
Également disponible via clic droit → ▶⤵ Démarrer ici.

40

Export EXE Standalone P3-A

build.py

python build.py remplace build.bat avec plus de fonctionnalites : detection modules, selecteur plugins, generation version_info.txt, smoke tests post-build, rapport HTML.

Commandes
python build.py # Build complet python build.py --no-tests # Sans tests python build.py --plugins # Selecteur plugins python build.py --clean # Nettoyer
Installeur NSIS

installer.nsi genere AutomationSequence-V8-Setup.exe avec raccourcis bureau/menu, association .asq, desinstallateur propre et mode silencieux /S pour SCCM/Intune.

makensis installer.nsi
Profil APPDATA

En mode EXE, prefs.json, history.db et scheduler.json sont stockes dans %APPDATA%\AutomationSequence\ pour permettre l installation dans C:\Program Files\ (lecture seule).

41

Web Dashboard Local P3-B

Serveur HTTP embarque exposant AutomationSequence via navigateur sur http://localhost:7890.

Activation

Onglet WEB, cocher Activer, choisir le port, sauvegarder. Ouvrir http://localhost:7890 dans le navigateur.

Fonctionnalites

Play/Stop/Step, compteurs OK/KO, graphe Chart.js, log SSE temps reel, variables (setter), sequence surlignee, historique sessions.

API REST

GET /status /vars /log /sequence /history /metrics /events (SSE) /health
POST /play /stop /step /vars/set /sequence/load

Exemple curl
curl -X POST http://localhost:7890/play -H "Authorization: Bearer TOKEN" curl -N http://localhost:7890/events curl http://localhost:7890/status
V8 FINAL — SSE temps réel fonctionnel : ThreadingHTTPServer remplace HTTPServer → Play/Stop/Step depuis le navigateur fonctionnels sans "Déconnecté". Connexions 127.0.0.1 : aucun token requis. Accès réseau distant : token Bearer obligatoire.
42

Assistant IA P3-C

L onglet ASSISTANT genere des sequences JSON a partir de descriptions en francais. Backend : Ollama local (offline) ou OpenAI/Azure.

Configuration

Cliquer Config IA dans l onglet Assistant.
Ollama (recommande) : provider=ollama, url=http://localhost:11434, model=llama3
OpenAI : provider=openai, cle=sk-..., model=gpt-4o-mini

Historique persistant

Sauvegarde dans ai_assistant_history.json. 100 derniers echanges conserves. Bouton Effacer pour reinitialiser le contexte.

Exemple

Vous ecrivez : Lis le CSV C:/data.csv et envoie chaque ligne par HTTP POST

{"sequence": [ {"type": "ReadCSV", "path": "C:/data.csv", "varName": "LIGNES"}, {"type": "ForEach", "listVar": "LIGNES", "itemVar": "LIGNE"}, {"type": "HttpPost", "url": "https://api.exemple.com", "body": "{"data": "$VAR{LIGNE}"}", "varName": "RESP"}, {"type": "LogMessage", "message": "$VAR{RESP}"}, {"type": "EndForEach"} ]}

Cliquer Inserer la sequence generee pour l ajouter a l editeur.

Installer Ollama

1. https://ollama.ai
2. ollama pull llama3 (4 Go RAM)
3. Ollama sur http://localhost:11434
4. Config IA dans AutomationSequence

Modeles recommandes

llama3 = equilibre qualite/vitesse (7B)
mistral = rapide (7B)
gemma2 = bon francais (9B)
llava = vision + texte
gpt-4o-mini = cloud OpenAI economique

35

Compatibilité V6 / Migration

✓ Inchangé V6/V7 → V8

Format JSON séquences · Actions Phases 1→6 · Vault Fernet V6 · history.db · scheduler.json · prefs.json (thèmes V6) · alert_config.json · recorder.py · variables.py · dashboard.py · scheduler.py

⬆ Étendu en V8

engine.py (+ checkpoint, profiler, async) · themes.py (+4 thèmes) · main.py (Command Palette, SmartForm, Bibliothèque, onglet Plugins) · CallSequence (+ scope, returnVar) · If (+ startswith, endswith)

★ Entièrement nouveau V7/V8

plugin_api.py · network_actions.py · ai_actions.py · agent_server.py · agent_client.py · audit.py · vault_v2.py · tests/ · build.bat · AutomationSequence.spec

Aucune séquence JSON V5/V6/V7 ne nécessite de modification pour fonctionner en V8. La migration consiste uniquement à remplacer les fichiers Python — les données (séquences, vault, historique) sont préservées intégralement.
43

Correctifs & Améliorations V8 FINAL V8 FINAL

🚀 Dashboard temps réel

Durée ⏱ en temps réel : nouveau callback on_action_done(idx, ok, dur_ms) dans engine.py → durée et résultat de chaque action remontés au dashboard instantanément.

Dernières actions : tableau Type / ms / Statut alimenté en direct pendant l'exécution.

on_start() / on_stop() : remise à zéro du dashboard à chaque nouvelle exécution.

📁 Historique couleurs corrigées

Statuts désormais cohérents : ✅ TERMINÉ → vert, ⛔ ARRÊTÉ → orange, erreurs → rouge.

Compatibilité statuts anglais legacy (finished, stopped) gérée automatiquement.

🌐 Web Dashboard SSE fonctionnel

ThreadingHTTPServer remplace HTTPServer : la connexion SSE tourne dans son propre thread. Plus de "Déconnecté". Log streaming, events action_ok/ko, sequence_end en temps réel.

Connexions 127.0.0.1 : aucun token requis. Token automatiquement injecté dans le HTML servi → boutons Play/Stop/Step fonctionnels.

📑 Barre multi-onglets

Barre d'onglets horizontale au-dessus de la zone principale. Bouton pour nouvelle séquence, clic pour basculer, × pour fermer. Chaque onglet conserve son état en mémoire.

Ctrl+T ouvre un fichier JSON dans un nouvel onglet.

🔌 Onglet Plugin auto-refresh

Plugins chargés après _build_ui() (fix crash au démarrage). Binding <<NotebookTabChanged>> → onglet Plugin se rafraîchit automatiquement à la sélection.

🔧 Fix AlertConfig

AlertConfig.load() retourne un dict. Fix : alert_cfg.on_erroralert_cfg.get("triggerOnError"). Les alertes SMTP fonctionnent désormais correctement.

📦 requirements.txt complété

plyer>=2.1.0 (notifications desktop) et pytest-json-report>=1.5.0 (rapports build.py) ajoutés. pip install -r requirements.txt installe tout sans erreur.