aetherius 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. aetherius/__init__.py +42 -0
  2. aetherius/__main__.py +12 -0
  3. aetherius/_contracts/__init__.py +0 -0
  4. aetherius/_contracts/blueprint.schema.json +144 -0
  5. aetherius/acts/__init__.py +1 -0
  6. aetherius/acts/_shared.py +61 -0
  7. aetherius/acts/continuum/__init__.py +7 -0
  8. aetherius/acts/continuum/actions.py +149 -0
  9. aetherius/acts/continuum/bridge.py +159 -0
  10. aetherius/acts/continuum/browser.py +164 -0
  11. aetherius/acts/continuum/debug_overlay.py +65 -0
  12. aetherius/acts/continuum/driver.py +127 -0
  13. aetherius/acts/continuum/human_actions.py +74 -0
  14. aetherius/acts/oracle/__init__.py +1 -0
  15. aetherius/acts/oracle/driver.py +1 -0
  16. aetherius/acts/oracle/locator.py +1 -0
  17. aetherius/acts/oracle/model.py +1 -0
  18. aetherius/acts/oracle/perception.py +1 -0
  19. aetherius/acts/phantom/__init__.py +1 -0
  20. aetherius/acts/phantom/driver.py +1 -0
  21. aetherius/acts/phantom/loop.py +1 -0
  22. aetherius/acts/phantom/memory.py +1 -0
  23. aetherius/acts/phantom/perception.py +1 -0
  24. aetherius/acts/phantom/planner.py +1 -0
  25. aetherius/acts/vector/__init__.py +1 -0
  26. aetherius/acts/vector/auth.py +108 -0
  27. aetherius/acts/vector/client.py +129 -0
  28. aetherius/acts/vector/driver.py +128 -0
  29. aetherius/builder/__init__.py +40 -0
  30. aetherius/builder/catalog.py +93 -0
  31. aetherius/builder/factory.py +243 -0
  32. aetherius/builder/templates.py +150 -0
  33. aetherius/builder/validation.py +120 -0
  34. aetherius/cli.py +236 -0
  35. aetherius/config/__init__.py +1 -0
  36. aetherius/config/secrets.py +71 -0
  37. aetherius/config/settings.py +44 -0
  38. aetherius/console/__init__.py +1 -0
  39. aetherius/console/app.py +66 -0
  40. aetherius/console/console.tcss +97 -0
  41. aetherius/console/daemon_control.py +83 -0
  42. aetherius/console/run_bridge.py +43 -0
  43. aetherius/console/screens/__init__.py +1 -0
  44. aetherius/console/screens/_pending.py +38 -0
  45. aetherius/console/screens/builder/__init__.py +1 -0
  46. aetherius/console/screens/builder/act_picker.py +75 -0
  47. aetherius/console/screens/builder/io_editor.py +167 -0
  48. aetherius/console/screens/builder/options_editor.py +132 -0
  49. aetherius/console/screens/builder/preview.py +57 -0
  50. aetherius/console/screens/builder/screen.py +235 -0
  51. aetherius/console/screens/builder/step_editor.py +249 -0
  52. aetherius/console/screens/catalog.py +52 -0
  53. aetherius/console/screens/home.py +90 -0
  54. aetherius/console/screens/library.py +124 -0
  55. aetherius/console/screens/library_scan.py +99 -0
  56. aetherius/console/screens/recorder.py +193 -0
  57. aetherius/console/screens/runs.py +138 -0
  58. aetherius/console/screens/sessions.py +14 -0
  59. aetherius/console/screens/settings.py +132 -0
  60. aetherius/console/screenshots.py +173 -0
  61. aetherius/console/theme.py +114 -0
  62. aetherius/console/widgets/__init__.py +1 -0
  63. aetherius/console/widgets/event_log.py +44 -0
  64. aetherius/console/widgets/form.py +101 -0
  65. aetherius/console/widgets/json_preview.py +18 -0
  66. aetherius/console/widgets/run_summary.py +82 -0
  67. aetherius/core/__init__.py +1 -0
  68. aetherius/core/actions/__init__.py +1 -0
  69. aetherius/core/actions/base.py +99 -0
  70. aetherius/core/actions/data.py +126 -0
  71. aetherius/core/actions/flow.py +76 -0
  72. aetherius/core/actions/interaction.py +109 -0
  73. aetherius/core/actions/navigation.py +32 -0
  74. aetherius/core/actions/registry.py +70 -0
  75. aetherius/core/actions/spec.py +42 -0
  76. aetherius/core/blueprint/__init__.py +1 -0
  77. aetherius/core/blueprint/loader.py +82 -0
  78. aetherius/core/blueprint/models.py +81 -0
  79. aetherius/core/blueprint/template.py +101 -0
  80. aetherius/core/blueprint/validator.py +45 -0
  81. aetherius/core/driver.py +36 -0
  82. aetherius/core/errors.py +134 -0
  83. aetherius/core/events/__init__.py +1 -0
  84. aetherius/core/events/bus.py +28 -0
  85. aetherius/core/events/models.py +29 -0
  86. aetherius/core/events/sinks.py +55 -0
  87. aetherius/core/extraction/__init__.py +1 -0
  88. aetherius/core/extraction/html_extractor.py +52 -0
  89. aetherius/core/extraction/json_extractor.py +125 -0
  90. aetherius/core/runtime/__init__.py +1 -0
  91. aetherius/core/runtime/context.py +61 -0
  92. aetherius/core/runtime/engine.py +188 -0
  93. aetherius/core/runtime/result.py +39 -0
  94. aetherius/core/runtime/selector.py +1 -0
  95. aetherius/models/__init__.py +1 -0
  96. aetherius/models/registry.py +1 -0
  97. aetherius/models/store/.gitkeep +0 -0
  98. aetherius/recorder/__init__.py +12 -0
  99. aetherius/recorder/_capture_js.py +80 -0
  100. aetherius/recorder/_gesture_js.py +40 -0
  101. aetherius/recorder/_names.py +20 -0
  102. aetherius/recorder/_overlay_js.py +262 -0
  103. aetherius/recorder/_playwright.py +49 -0
  104. aetherius/recorder/_selector_js.py +148 -0
  105. aetherius/recorder/_transform.py +214 -0
  106. aetherius/recorder/_vector_js.py +174 -0
  107. aetherius/recorder/base.py +92 -0
  108. aetherius/recorder/blueprint_recorder.py +72 -0
  109. aetherius/recorder/capture.py +59 -0
  110. aetherius/recorder/continuum_backend.py +119 -0
  111. aetherius/recorder/gesture_recorder.py +193 -0
  112. aetherius/recorder/selector_synth.py +83 -0
  113. aetherius/recorder/session.py +101 -0
  114. aetherius/recorder/vector_backend.py +158 -0
  115. aetherius/server/__init__.py +12 -0
  116. aetherius/server/app.py +37 -0
  117. aetherius/server/config.py +25 -0
  118. aetherius/server/deps.py +50 -0
  119. aetherius/server/jobs.py +155 -0
  120. aetherius/server/routes/__init__.py +1 -0
  121. aetherius/server/routes/blueprints.py +45 -0
  122. aetherius/server/routes/recorder.py +25 -0
  123. aetherius/server/routes/runs.py +49 -0
  124. aetherius/server/routes/stream.py +53 -0
  125. aetherius/server/schemas.py +78 -0
  126. aetherius/stealth/__init__.py +1 -0
  127. aetherius/stealth/fingerprint/__init__.py +1 -0
  128. aetherius/stealth/fingerprint/patch.py +38 -0
  129. aetherius/stealth/fingerprint/profile.py +95 -0
  130. aetherius/stealth/gestures/__init__.py +1 -0
  131. aetherius/stealth/gestures/data/human_library.json +7107 -0
  132. aetherius/stealth/gestures/library.py +126 -0
  133. aetherius/stealth/gestures/seed.py +97 -0
  134. aetherius/stealth/humanizer/__init__.py +1 -0
  135. aetherius/stealth/humanizer/input.py +89 -0
  136. aetherius/stealth/humanizer/keyboard.py +75 -0
  137. aetherius/stealth/humanizer/mouse.py +153 -0
  138. aetherius/stealth/humanizer/scroll.py +55 -0
  139. aetherius/stealth/humanizer/timing.py +54 -0
  140. aetherius/stealth/ml/__init__.py +1 -0
  141. aetherius/stealth/ml/fingerprint_model.py +1 -0
  142. aetherius/stealth/ml/motion_model.py +1 -0
  143. aetherius/stealth/policy.py +133 -0
  144. aetherius/stealth/session/__init__.py +1 -0
  145. aetherius/stealth/session/store.py +35 -0
  146. aetherius/stealth/session/warmup.py +52 -0
  147. aetherius/version.py +3 -0
  148. aetherius-0.2.0.data/data/aetherius/_contracts/__init__.py +0 -0
  149. aetherius-0.2.0.data/data/aetherius/_contracts/blueprint.schema.json +144 -0
  150. aetherius-0.2.0.dist-info/METADATA +606 -0
  151. aetherius-0.2.0.dist-info/RECORD +154 -0
  152. aetherius-0.2.0.dist-info/WHEEL +4 -0
  153. aetherius-0.2.0.dist-info/entry_points.txt +2 -0
  154. aetherius-0.2.0.dist-info/licenses/LICENSE +11 -0
@@ -0,0 +1,606 @@
1
+ Metadata-Version: 2.4
2
+ Name: aetherius
3
+ Version: 0.2.0
4
+ Summary: A fixed, robust web-bot engine driven by declarative instruction files (Blueprints).
5
+ Project-URL: Repository, https://github.com/kln-mltre/Aetherius
6
+ Author: Kylian Malartre
7
+ License: Aetherius
8
+ Copyright (c) 2026 Kylian MALARTRE (kln-mltre)
9
+
10
+ This work is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License.
11
+
12
+ To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
13
+
14
+ COMMERCIAL USE RESTRICTION
15
+ Any commercial use, including but not limited to selling the software, offering it as a paid service (SaaS), or using it to generate revenue directly or indirectly, is strictly prohibited without prior written consent from the author.
16
+
17
+ For commercial licensing inquiries or dual-licensing options, please contact the author directly.
18
+ License-File: LICENSE
19
+ Keywords: agent,automation,bot,browser,playwright,scraping,stealth
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: fastapi>=0.110
22
+ Requires-Dist: httpx>=0.27
23
+ Requires-Dist: jinja2>=3.1
24
+ Requires-Dist: jsonpath-ng>=1.6
25
+ Requires-Dist: jsonschema>=4.21
26
+ Requires-Dist: parsel>=1.9
27
+ Requires-Dist: pydantic-settings>=2.2
28
+ Requires-Dist: pydantic>=2.6
29
+ Requires-Dist: python-dotenv>=1.0
30
+ Requires-Dist: pyyaml>=6.0
31
+ Requires-Dist: questionary>=2.0
32
+ Requires-Dist: rich>=13.7
33
+ Requires-Dist: tenacity>=8.2
34
+ Requires-Dist: textual>=0.60
35
+ Requires-Dist: typer>=0.12
36
+ Requires-Dist: uvicorn[standard]>=0.29
37
+ Requires-Dist: websockets>=12.0
38
+ Provides-Extra: agent
39
+ Requires-Dist: anthropic>=0.25; extra == 'agent'
40
+ Provides-Extra: all
41
+ Requires-Dist: anthropic>=0.25; extra == 'all'
42
+ Requires-Dist: numpy>=1.26; extra == 'all'
43
+ Requires-Dist: onnxruntime>=1.17; extra == 'all'
44
+ Requires-Dist: opencv-python-headless>=4.9; extra == 'all'
45
+ Requires-Dist: pillow>=10.3; extra == 'all'
46
+ Requires-Dist: playwright>=1.44; extra == 'all'
47
+ Provides-Extra: browser
48
+ Requires-Dist: playwright>=1.44; extra == 'browser'
49
+ Provides-Extra: dev
50
+ Requires-Dist: build>=1.2; extra == 'dev'
51
+ Requires-Dist: mypy>=1.9; extra == 'dev'
52
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
53
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
54
+ Requires-Dist: pytest>=8.1; extra == 'dev'
55
+ Requires-Dist: ruff>=0.4; extra == 'dev'
56
+ Requires-Dist: twine>=5.0; extra == 'dev'
57
+ Provides-Extra: stealth
58
+ Requires-Dist: numpy>=1.26; extra == 'stealth'
59
+ Provides-Extra: vision
60
+ Requires-Dist: numpy>=1.26; extra == 'vision'
61
+ Requires-Dist: onnxruntime>=1.17; extra == 'vision'
62
+ Requires-Dist: opencv-python-headless>=4.9; extra == 'vision'
63
+ Requires-Dist: pillow>=10.3; extra == 'vision'
64
+ Description-Content-Type: text/markdown
65
+
66
+ # Aetherius
67
+
68
+ ```text
69
+ ▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚
70
+ ˚ ✦ · ✦ · ˚ ✦ · ˚ · ✦ · ˚ ✦ · ✦ ˚
71
+ █████╗ ███████╗████████╗██╗ ██╗███████╗██████╗ ██╗██╗ ██╗███████╗
72
+ ██╔══██╗██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔══██╗██║██║ ██║██╔════╝
73
+ ███████║█████╗ ██║ ███████║█████╗ ██████╔╝██║██║ ██║███████╗
74
+ ██╔══██║██╔══╝ ██║ ██╔══██║██╔══╝ ██╔══██╗██║╚██╗ ██╔╝╚════██║
75
+ ██║ ██║███████╗ ██║ ██║ ██║███████╗██║ ██║██║ ╚████╔╝ ███████║
76
+ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚══════╝
77
+ ❧──────────────────── ❦ ────────────────────❧
78
+ ✦ per nubes, ad aethera ✦
79
+ ▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚▞▚
80
+ ```
81
+
82
+ > Se veut le produit du concept de bot web modulaire, poussé à son paroxysme.
83
+ > Capable de réaliser, sur la base d'un simple fichier d'instructions, n'importe quelle tâche.
84
+
85
+ ## La vision
86
+
87
+ Dans la plupart des projets on réécrit le même code fragile : requêtes `axios`/HTTP, scraping,
88
+ automatisation de navigateur. C'est répétitif, fastidieux, et ça casse dès que le site ou l'API
89
+ change — il faut alors éditer ce code éparpillé dans chaque projet.
90
+
91
+ **Aetherius inverse le problème.** Le moteur du bot est fixe et robuste. Le comportement, lui, est
92
+ décrit dans un **fichier d'instructions déclaratif** (un *Blueprint*, en JSON). Quand un site
93
+ change, on corrige **un Blueprint**, pas N codebases. Et parce que le moteur est exposé via un
94
+ **daemon local**, on le pilote depuis **n'importe quel langage** (TypeScript, Python, …) avec le
95
+ même fichier d'instructions.
96
+
97
+ Aetherius est conçu pour être **exporté comme bibliothèque** et alimenter tous les projets :
98
+ récupérer un emploi du temps via API, scraper une page derrière un login, publier une vidéo en
99
+ restant indétectable, ou lâcher un agent autonome sur une tâche non scriptée.
100
+
101
+ Aetherius est à la fois une **bibliothèque** (consommée en direct ou via un daemon par les apps clientes)
102
+ et un **outil** : une **Console dans le terminal** pour créer, tester et gérer tout ça sans écrire
103
+ une ligne de JSON à la main.
104
+
105
+ <p align="center"><sub>▚▞▚ ✦ ▞▚▞</sub></p>
106
+
107
+ ## Le concept : 4 Acts
108
+
109
+ Aetherius est un interprète qui joue en quatre **Acts**, du plus léger au plus puissant. Le
110
+ Blueprint choisit l'Act adapté à la tâche.
111
+
112
+ | Act | Nom | Moteur | Quand l'utiliser |
113
+ |-----|-----|--------|------------------|
114
+ | **I** | **Vector** | Requêtes HTTP/API | Les données sont derrière une API ou des endpoints stables. Le cas « axios ». Le plus rapide. |
115
+ | **II** | **Continuum** | Navigateur scripté (Playwright) | Il faut un vrai navigateur : login, JS, session, DOM. Sélecteurs connus et stables. |
116
+ | **III** | **Oracle** | Navigateur guidé par vision + discrétion | L'UI est fragile/obfusquée : Aetherius « voit » l'écran via un petit modèle entraîné et agit avec discrétion. |
117
+ | **IV** | **Phantom** | Agent autonome | Objectif non scripté. Perçoit, raisonne, agit en boucle. Résilience maximale. Le plus lourd. |
118
+
119
+ Plus l'Act est élevé, plus le Blueprint est **haut-niveau** (on décrit *quoi*, plus *comment*) et
120
+ plus les dépendances sont lourdes (installées à la demande via des *extras*).
121
+
122
+ ### Act I — Vector
123
+ Client HTTP robuste : requêtes GET/POST, encodage form/JSON, en-têtes, retries avec backoff,
124
+ pagination, stratégies d'authentification (cookie, bearer, basic, form-login type CAS), extraction
125
+ déclarative (JSONPath pour le JSON, CSS/XPath pour le HTML). Remplace les services `axios` écrits à
126
+ la main ; les constantes magiques disséminées deviennent des `inputs` typés et documentés.
127
+
128
+ ### Act II — Continuum
129
+ Automatisation d'un vrai navigateur (Playwright) qui suit le Blueprint à la lettre : navigation,
130
+ remplissage, clics, attentes, extraction DOM, bridge JavaScript injecté. Gère les scénarios qui
131
+ exigent un navigateur : login, cookies de session, contenu rendu par JS. C'est l'équivalent propre
132
+ et réutilisable d'une « WebView cachée qui scrape ». Discrétion optionnelle.
133
+
134
+ ### Act III — Oracle
135
+ Quand les sélecteurs sont trop fragiles ou absents, Oracle **regarde l'écran**. Un petit modèle de
136
+ vision entraîné spécifiquement pour la tâche (exporté en ONNX) localise les éléments cibles sur des
137
+ captures d'écran ; Aetherius clique par coordonnées à travers la couche de discrétion. Idéal pour
138
+ les interfaces qui changent souvent ou piègent les bots.
139
+
140
+ ### Act IV — Phantom
141
+ Un agent décisionnel autonome. Boucle **percevoir → raisonner → agir** : il perçoit la page (vision
142
+ + DOM + arbre d'accessibilité), un planner (par défaut Claude, ex. `claude-fable-5` /
143
+ `claude-opus-4-8`, remplaçable par un VLM local) décide de l'action suivante, et l'action est jouée
144
+ via la couche de discrétion. Pour les objectifs non scriptés et la résilience maximale.
145
+
146
+ > Aetherius est destiné à l'automatisation **autorisée** : ses propres comptes, ses propres données,
147
+ > ses propres workflows.
148
+
149
+ <p align="center"><sub>▚▞▚ ✦ ▞▚▞</sub></p>
150
+
151
+ ## Les fichiers d'instructions : les Blueprints
152
+
153
+ Un Blueprint est un fichier JSON déclaratif et versionné. Enveloppe :
154
+
155
+ ```json
156
+ {
157
+ "aetherius": "1.0",
158
+ "name": "domaine.tache",
159
+ "act": "vector",
160
+ "inputs": { "param": { "type": "string", "required": true } },
161
+ "secrets": ["cle_injectee_au_runtime"],
162
+ "vars": { "domain": "https://exemple.fr" },
163
+ "options": {
164
+ "debug": false,
165
+ "stealth": "off",
166
+ "session": { "profile": "mon-profil", "persist": true },
167
+ "timeout_ms": 30000,
168
+ "retries": { "max": 3, "backoff": "exponential" }
169
+ },
170
+ "steps": [ /* la séquence d'actions */ ],
171
+ "outputs": { "resultat": "{{ steps.x.champ }}" }
172
+ }
173
+ ```
174
+
175
+ - **inputs** : paramètres typés (le Blueprint est réutilisable, pas figé sur une valeur).
176
+ - **secrets** : identifiants/token fournis au runtime, **jamais** écrits dans le fichier (résolus
177
+ depuis l'environnement / un `.env` local — voir [docs/secrets.md](docs/secrets.md)).
178
+ - **vars** : constantes locales (domaines, chemins).
179
+ - **options** : `debug`, `stealth`, `session`, `timeout_ms`, `retries`.
180
+ - **steps** : le *dictionnaire d'actions* (navigate, click, fill, type, http.request, extract,
181
+ wait, if, for_each, …). Chaque Act déclare quelles actions il supporte ; un Blueprint qui demande
182
+ une action non supportée par son Act échoue à la validation, avec un message clair.
183
+ - **outputs** : la forme des données retournées, via interpolation `{{ }}`.
184
+
185
+ Le format est défini une fois pour toutes dans [`contracts/blueprint.schema.json`](contracts/blueprint.schema.json).
186
+ Des exemples exécutables (dérivés de vrais projets) sont dans [`examples/`](examples/).
187
+
188
+ ### Exemple — Act I (Vector) : emploi du temps par API
189
+ Voir [`examples/vector/ukit-planning-week.blueprint.json`](examples/vector/ukit-planning-week.blueprint.json).
190
+
191
+ ```json
192
+ {
193
+ "aetherius": "1.0",
194
+ "name": "ukit.planning.week",
195
+ "act": "vector",
196
+ "inputs": {
197
+ "group": { "type": "string", "required": true },
198
+ "monday": { "type": "string", "format": "date", "required": true }
199
+ },
200
+ "vars": { "domain": "https://ade-web.exemple.fr" },
201
+ "steps": [
202
+ {
203
+ "id": "week",
204
+ "action": "http.request",
205
+ "method": "POST",
206
+ "url": "{{ vars.domain }}/calendar/data",
207
+ "headers": {
208
+ "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
209
+ "Accept": "application/json"
210
+ },
211
+ "form": {
212
+ "start": "{{ inputs.monday }}",
213
+ "end": "{{ inputs.monday | add_days(7) }}",
214
+ "resType": "103",
215
+ "calView": "agendaWeek",
216
+ "federationIds[]": "{{ inputs.group }}",
217
+ "colourScheme": "3"
218
+ },
219
+ "expect": { "status": 200 },
220
+ "extract": {
221
+ "events": {
222
+ "from": "json", "path": "$[*]",
223
+ "where": "item.eventCategory != 'Vacances'",
224
+ "fields": {
225
+ "id": "$.id", "start": "$.start", "end": "$.end",
226
+ "category": "$.eventCategory", "color": "$.backgroundColor",
227
+ "description": "$.description"
228
+ }
229
+ }
230
+ }
231
+ }
232
+ ],
233
+ "outputs": { "events": "{{ steps.week.events }}" }
234
+ }
235
+ ```
236
+ Les constantes autrefois codées en dur (`resType`, `colourScheme`) sont explicites, le filtrage
237
+ `Vacances` et le parsing sont déclaratifs, et le groupe/la date sont des `inputs` réutilisables.
238
+
239
+ ### Exemple — Act II (Continuum) : login CAS + scraping
240
+ Voir [`examples/continuum/ukit-scolarite-login.blueprint.json`](examples/continuum/ukit-scolarite-login.blueprint.json).
241
+
242
+ ```json
243
+ {
244
+ "aetherius": "1.0",
245
+ "name": "ukit.scolarite.cold",
246
+ "act": "continuum",
247
+ "secrets": ["cas_user", "cas_pass"],
248
+ "options": { "session": { "profile": "scolarite", "persist": true }, "debug": false },
249
+ "steps": [
250
+ { "action": "navigate", "url": "https://cas.exemple.fr/login" },
251
+ { "action": "fill", "selector": "#username", "value": "{{ secrets.cas_user }}" },
252
+ { "action": "fill", "selector": "#password", "value": "{{ secrets.cas_pass }}" },
253
+ { "action": "click", "selector": "input[name=submit]" },
254
+ { "action": "wait_for", "selector": ".ent-dashboard", "timeout_ms": 15000,
255
+ "on_timeout": "fail:LOGIN_FAILED" },
256
+ { "action": "emit", "event": "LOGIN_SUCCESS" },
257
+ { "action": "navigate", "url": "https://ent.exemple.fr/dossier" },
258
+ { "action": "extract", "outputs": {
259
+ "firstName": { "selector": ".identity .firstname", "as": "text" },
260
+ "studentNumber": { "selector": "#num-etudiant", "as": "text" },
261
+ "ine": { "selector": "#ine", "as": "text" },
262
+ "email": { "selector": ".mail", "as": "text" }
263
+ }},
264
+ { "action": "navigate", "url": "https://webmail.exemple.fr" },
265
+ { "action": "extract", "outputs": { "unread": { "selector": ".unread-count", "as": "number" } } }
266
+ ]
267
+ }
268
+ ```
269
+ Les sélecteurs sont désormais des **données** (plus du JS injecté codé en dur), le flux de login est
270
+ déclaratif, et les événements (`LOGIN_SUCCESS`, …) restent disponibles pour suivre la progression.
271
+
272
+ ### Exemple — Act III (Oracle) : upload avec discrétion
273
+ Voir [`examples/oracle/tiktok-upload.blueprint.json`](examples/oracle/tiktok-upload.blueprint.json).
274
+
275
+ ```json
276
+ {
277
+ "aetherius": "1.0",
278
+ "name": "tiktok.upload",
279
+ "act": "oracle",
280
+ "inputs": {
281
+ "video": { "type": "path", "required": true },
282
+ "caption": { "type": "string", "required": true }
283
+ },
284
+ "options": {
285
+ "session": { "profile": "tiktok", "persist": true },
286
+ "stealth": {
287
+ "mouse": "gestures", "keyboard": "human", "scroll": "eased",
288
+ "timing": { "distraction": 0.1 }, "fingerprint": "chrome-desktop"
289
+ },
290
+ "debug": false
291
+ },
292
+ "vision": { "model": "tiktok-studio-ui@1" },
293
+ "steps": [
294
+ { "action": "navigate", "url": "https://www.tiktok.com/tiktokstudio/upload?lang=fr" },
295
+ { "action": "wait", "min_ms": 3500, "max_ms": 6000 },
296
+ { "action": "upload", "target": { "vision": "upload dropzone" }, "file": "{{ inputs.video }}" },
297
+ { "action": "type", "target": { "vision": "caption textarea" }, "text": "{{ inputs.caption }}" },
298
+ { "action": "wait", "min_ms": 2000, "max_ms": 4500 },
299
+ { "action": "click", "target": { "vision": "Post button" } },
300
+ { "action": "wait_for", "target": { "vision": "publish success toast" }, "timeout_ms": 35000 }
301
+ ]
302
+ }
303
+ ```
304
+
305
+ <p align="center"><sub>▚▞▚ ✦ ▞▚▞</sub></p>
306
+
307
+ ## La Console Aetherius : tout gérer depuis le terminal
308
+
309
+ Aetherius n'est pas qu'une bibliothèque : c'est aussi une **Console interactive dans le terminal**
310
+ (construite avec Textual), le centre de contrôle de l'outil. On la lance simplement :
311
+
312
+ ```bash
313
+ aetherius # ouvre la Console
314
+ ```
315
+
316
+ ![La Console Aetherius : écran d'accueil](docs/screenshots/home.svg)
317
+
318
+ > **État actuel** : la Console est navigable de bout en bout. Library, Runs, Catalog, le **Recorder**,
319
+ > le **Blueprint Studio** et **Settings** (démarrer/arrêter le daemon) sont pleinement fonctionnels
320
+ > pour Act I (Vector) et Act II (Continuum, avec l'extra `[browser]`) ; seul **Sessions** affiche
321
+ > honnêtement son jalon en attente (stealth/session). Détails : [docs/console.md](docs/console.md).
322
+
323
+ Depuis la Console, sans écrire de JSON à la main :
324
+ - **Créer et éditer des Blueprints** via le **Blueprint Studio** (voir plus bas).
325
+ - **Lancer des runs** et suivre en direct leurs événements, logs et artefacts.
326
+ - **Explorer et comprendre** les 4 Acts et les modèles de vision disponibles (fiches explicatives).
327
+ - **Gérer les profils/sessions** persistants et lancer un warmup.
328
+ - **Piloter le daemon** (démarrer/arrêter) et la configuration.
329
+ - **Parcourir la bibliothèque** de Blueprints (dupliquer, éditer, supprimer).
330
+
331
+ ### Créer un Blueprint : trois voies
332
+
333
+ 1. **Le Blueprint Studio (guidé, rapide, sans JSON)** — dans la Console. Sélection de l'Act (avec
334
+ son explication), ajout des steps via des formulaires, **aperçu JSON live** validé contre le
335
+ schéma en temps réel. L'option la plus rapide pour la majorité des cas.
336
+ 2. **Le Recorder (par démonstration)** — pour les tâches d'automatisation navigateur : l'action est
337
+ réalisée dans un navigateur visible, Aetherius capture et recrache un Blueprint propre, avec
338
+ **synthèse de sélecteurs robustes** (privilégie `data-testid`/aria/texte avant les chemins CSS
339
+ fragiles). Idéal quand la démonstration directe est plus simple que la description.
340
+ 3. **JSON à la main** — pour les power users qui veulent le contrôle total.
341
+
342
+ ![Le Blueprint Studio : construction guidée avec aperçu JSON validé en direct](docs/screenshots/studio.svg)
343
+
344
+ La logique de construction vit dans un module `builder/` *headless* : la Console n'en est que
345
+ l'habillage, et le daemon peut l'exposer pour construire des Blueprints programmatiquement.
346
+ Prise en main illustrée : [docs/builder.md](docs/builder.md).
347
+
348
+ ## La discrétion (stealth), en option modulaire
349
+
350
+ La discrétion n'est **pas** liée à un Act : c'est une couche transverse activée par
351
+ `options.stealth`, applicable à tout Act qui pilote un navigateur (II, III, IV). Désactivée par
352
+ défaut (no-op).
353
+
354
+ Techniques disponibles (issues et généralisées du système *BioMouse* éprouvé) :
355
+ - **Souris humaine** : rejeu d'un geste humain *réellement enregistré*, transformé
356
+ géométriquement (mise à l'échelle + rotation) pour atteindre n'importe quelle cible. Matching du
357
+ meilleur geste par distance et angle, timing inter-points préservé à la microseconde. Clics
358
+ off-center (30–70 % de l'élément), micro-pauses avant/pendant le clic.
359
+ - **Clavier humain** : vitesse variable par session, fautes de frappe suivies de corrections,
360
+ délais accrus sur les espaces et caractères spéciaux.
361
+ - **Scroll humain** : courbe d'easing ease-out cubique (départ rapide, fin douce).
362
+ - **Timing humain** : délais aléatoires, pauses « distraction » occasionnelles, parking du curseur
363
+ pendant les attentes longues.
364
+ - **Fingerprint** : masquage `navigator.webdriver`, `chrome.runtime`, `plugins`, `permissions` ;
365
+ profils de fingerprint cohérents (UA, viewport, timezone, WebGL, canvas).
366
+ - **Profils persistants + warmup** : réutilisation d'un profil navigateur pour construire un
367
+ historique authentique (cookies, cache) avant l'automatisation.
368
+
369
+ Activation :
370
+ ```json
371
+ "options": { "stealth": { "mouse": "gestures", "keyboard": "human", "fingerprint": "chrome-desktop" } }
372
+ ```
373
+ `"stealth": "off"` (défaut) ou `"stealth": "nom-de-preset"` sont aussi acceptés.
374
+
375
+ **IA pour la discrétion ?** Approche hybride retenue : le rejeu géométrique de gestes est le moteur
376
+ par défaut (léger, éprouvé, score reCAPTCHA élevé) — **pas besoin d'IA**. Deux upgrades ML
377
+ *optionnels* sont prévus derrière la même interface : un modèle génératif de mouvements (pour ne pas
378
+ se limiter à une bibliothèque finie de gestes) et un modèle de fingerprints cohérents. À activer
379
+ seulement si un cas d'usage le justifie.
380
+
381
+ ## Le mode Debug
382
+
383
+ `options.debug: true` :
384
+ - **Acts navigateur (II/III/IV)** : fenêtre visible, overlay du curseur, surlignage des cibles,
385
+ ralenti (slow-mo). Idéal pour comprendre pourquoi un step échoue.
386
+ - **Acts sans navigateur (I)** : logs terminal structurés (requêtes, réponses, extractions).
387
+ - Tous les Acts émettent des **événements** consommables (progression, artefacts : screenshots,
388
+ HAR, snapshots DOM) écrits dans un répertoire de run.
389
+
390
+ ## Le Gesture Recorder
391
+
392
+ En complément, un *gesture recorder* capture des traces de souris humaines réelles pour enrichir la
393
+ bibliothèque de gestes du système de discrétion. (Le Blueprint recorder, lui, est décrit plus haut
394
+ dans « Créer un Blueprint : trois voies ».)
395
+
396
+ <p align="center"><sub>▚▞▚ ✦ ▞▚▞</sub></p>
397
+
398
+ ## Interopérabilité multi-langage
399
+
400
+ Le cœur est en Python ; il est exposé à tous les langages via un **daemon local**.
401
+
402
+ ```
403
+ ┌─────────────┐ Blueprint + inputs + secrets ┌──────────────────────────┐
404
+ │ App │ ────────────────────────────────► │ Aetherius Daemon │
405
+ │ (TS/Python) │ HTTP + WebSocket │ (FastAPI) │
406
+ │ SDK mince │ ◄──────────────────────────────── │ Runtime → Act I..IV │
407
+ └─────────────┘ résultat + flux d'événements └──────────────────────────┘
408
+ ```
409
+
410
+ - **Daemon** : `aetherius serve` (local, 127.0.0.1, token optionnel, `GET /health`).
411
+ - `POST /v1/runs` → `run_id` ; `GET /v1/runs/{id}` → statut + résultat.
412
+ - `WS /v1/runs/{id}/events` → flux d'événements (rejeu + live jusqu'à `done`).
413
+ - `POST /v1/blueprints/validate`, `GET /v1/schema`. `POST /v1/recorder/sessions` : `501`,
414
+ l'enregistrement reste host-local (CLI/Console).
415
+ - **SDK TypeScript** `@aetherius/client` (Node 20+) : spawn le daemon (ou cible un `baseUrl`),
416
+ `client.run(blueprint, { inputs, secrets, onEvent })`, stream d'événements typé.
417
+ - **SDK Python** : l'import in-process direct (`import aetherius`, sans daemon) ; le client remote
418
+ mince est différé.
419
+ - **Contrats** ([`contracts/`](contracts/)) : JSON Schema du Blueprint + OpenAPI du daemon + schéma
420
+ d'événements = source de vérité ; les types des SDK s'y conforment (gardés par des tests).
421
+
422
+ Détails, sécurité et « Tester le daemon » : [docs/daemon.md](docs/daemon.md).
423
+
424
+ ### Exécuter un Blueprint depuis le code applicatif
425
+
426
+ La Console sert à *créer et gérer* les Blueprints. L'**exécution**, elle, se fait directement depuis
427
+ le code applicatif, en chargeant un Blueprint **existant** — la Console n'est jamais requise au runtime.
428
+
429
+ Python (in-process, sans daemon) :
430
+ ```python
431
+ from aetherius import Aetherius
432
+
433
+ client = Aetherius()
434
+ result = client.run(
435
+ "blueprints/ukit-planning-week.blueprint.json",
436
+ inputs={"group": "TP-A1", "monday": "2026-09-07"},
437
+ )
438
+ print(result.outputs["events"])
439
+ ```
440
+
441
+ TypeScript (via le daemon local, spawné automatiquement) :
442
+ ```ts
443
+ import { Aetherius } from "@aetherius/client";
444
+
445
+ const client = new Aetherius();
446
+ const result = await client.run("blueprints/ukit-planning-week.blueprint.json", {
447
+ inputs: { group: "TP-A1", monday: "2026-09-07" },
448
+ });
449
+ console.log(result.outputs.events);
450
+ ```
451
+
452
+ <p align="center"><sub>▚▞▚ ✦ ▞▚▞</sub></p>
453
+
454
+ ## Architecture du dépôt
455
+
456
+ ```
457
+ src/aetherius/
458
+ core/ blueprint (models/loader/validator/template), actions (le dictionnaire),
459
+ runtime (engine/context/selector/result), extraction, events, errors, driver
460
+ acts/ vector (I), continuum (II), oracle (III), phantom (IV)
461
+ stealth/ policy, humanizer (mouse/keyboard/scroll/timing), gestures, fingerprint,
462
+ session (store/warmup), ml (optionnel)
463
+ recorder/ blueprint_recorder, gesture_recorder, capture, selector_synth
464
+ builder/ construction headless de Blueprint (factory, catalog, templates)
465
+ console/ interface terminale globale (Textual) : Blueprint Studio, runs, catalogue,
466
+ sessions, settings — la porte d'entrée de l'outil
467
+ models/ registry + cache des assets ML runtime
468
+ server/ daemon FastAPI (routes/jobs/schemas)
469
+ config/ settings
470
+ contracts/ blueprint.schema.json, openapi.yaml, events.schema.json (source de vérité)
471
+ sdks/ typescript (@aetherius/client), python
472
+ examples/ Blueprints de démonstration
473
+ training/ entraînement des modèles Oracle (hors runtime)
474
+ legacy_examples/ code de référence des projets d'origine (UKit, TikTok) + carte de provenance
475
+ ```
476
+
477
+ Principe : chaque fichier de logique reste sous ~300 lignes ; typage strict (pydantic) ; erreurs
478
+ typées (jamais avalées) ; les Acts sont des drivers interchangeables derrière une interface commune.
479
+
480
+ ## Installation (cible)
481
+
482
+ ```bash
483
+ pip install aetherius # cœur + Act I (Vector) + daemon + Console
484
+ pip install aetherius[browser] # + Act II (Continuum)
485
+ pip install aetherius[vision] # + Act III (Oracle)
486
+ pip install aetherius[agent] # + Act IV (Phantom)
487
+ pip install aetherius[all]
488
+ ```
489
+
490
+ Puis pour lancer la Console :
491
+ ```bash
492
+ aetherius # centre de contrôle interactif dans le terminal
493
+ ```
494
+
495
+ ## Développement
496
+
497
+ Pour travailler sur Aetherius (et pas seulement le consommer). Prérequis : Python 3.11+ et, pour le
498
+ SDK TypeScript, Node 20+.
499
+
500
+ ```bash
501
+ git clone <repo> && cd Aetherius
502
+ make install-dev # installe le paquet en editable + les outils de dev
503
+ ```
504
+
505
+ Le `Makefile` est le point d'entrée unique — les mêmes cibles servent en local et en CI :
506
+
507
+ ```bash
508
+ make check # avant de commit : format + lint (ruff) + types (mypy) + tests (pytest)
509
+ make test # tests seuls, avec couverture
510
+ make check-all # tout le dépôt : Python + SDK TypeScript
511
+ make help # liste des cibles
512
+ ```
513
+
514
+ Conventions de contribution (discipline de test, invariants, structure des tests) :
515
+ [`CONTRIBUTING.md`](CONTRIBUTING.md) et [`docs/testing.md`](docs/testing.md).
516
+
517
+ <p align="center"><sub>▚▞▚ ✦ ▞▚▞</sub></p>
518
+
519
+ ## État d'avancement
520
+
521
+ Le projet avance en deux grandes phases. La **Phase 1** — le socle, utilisable comme **bibliothèque**
522
+ (in-process Python) et comme **service** (daemon + SDK) — est **terminée avec ce jalon** : un premier
523
+ point de contrôle, à éprouver en conditions réelles avant d'attaquer la **Phase 2** (les deux Acts les
524
+ plus lourds).
525
+
526
+ ### Phase 1 — le socle réutilisable (terminée)
527
+
528
+ - [x] Vision, concept des 4 Acts, format Blueprint, architecture.
529
+ - [x] Squelette : arborescence + stubs + contrats + exemples.
530
+ - [x] **Act I — Vector** : moteur HTTP/API complet. `Aetherius().run(blueprint, inputs=...)` fonctionnel. Couverture : http.request (form/JSON/params/headers), extraction JSONPath avec `where` et mapping de champs, extraction HTML CSS/XPath, authentification (NoAuth/Bearer/Basic/Cookie/CAS form-login), retries/backoff (tenacity), moteur de templates Jinja2 (`{{ inputs.x | add_days(7) }}`), bus d'événements, hiérarchie d'erreurs typées. 69 tests, mypy strict, lint propre.
531
+ - [x] **Console (Textual)** : navigation complète (`aetherius` ou `aetherius console`) — Library,
532
+ Runs et Catalog fonctionnels pour Act I (parcours des Blueprints, exécution avec formulaire
533
+ d'inputs/secrets et flux d'événements en direct, catalogue des 4 Acts). CLI scriptable
534
+ (`aetherius run|validate|record`). Le Recorder et le Blueprint Studio sont fonctionnels (voir
535
+ ci-dessous) ; seuls Sessions et Settings affichent leur jalon en attente ; voir
536
+ [docs/console.md](docs/console.md).
537
+ - [x] **Act II — Continuum** : automatisation d'un vrai navigateur (Playwright, API synchrone).
538
+ Actions navigateur (navigate/back/forward/reload, click/fill/type/press/select/hover/scroll/
539
+ upload/drag), `wait_for` avec échec nommé (`on_timeout: "fail:CODE"`), extraction DOM typée
540
+ (text/number/html/attr/count), `evaluate` (JS injecté), `screenshot` (artefact), sessions
541
+ persistantes (profils réutilisés) et mode debug (fenêtre visible + slow-mo). Actions utilitaires
542
+ partagées avec Vector via un mixin (zéro duplication). Extra `[browser]` chargé à la demande ;
543
+ `import aetherius` reste léger. Tests unitaires (page factice, CI de base) + intégration vrai
544
+ Chromium (job CI dédié). Discrétion : **branchée** (voir ci-dessous).
545
+ - [x] **Système de discrétion** : couche transverse activée par `options.stealth`, branchée dans
546
+ Continuum. `StealthPolicy` (off / preset / config fine). Fingerprint (masques `navigator.webdriver`/
547
+ `chrome.runtime`/`permissions`/`plugins` + profil cohérent UA/viewport/timezone/WebGL,
548
+ `chrome-desktop`). Souris humaine par rejeu géométrique de gestes (scale+rotation, timing préservé,
549
+ clic off-center), bibliothèque **source-agnostique** amorcée par un seed synthétique (min-jerk),
550
+ ouverte au recorder et au ML. Frappe humaine (typos+correction, délais), scroll ease-out, timing
551
+ avec distraction, warmup de profil. Cœur **stdlib pur** (tests en CI de base) ; intégration Chromium
552
+ réelle. Exemple : `examples/continuum/quotes-stealth.blueprint.json`. Détails :
553
+ [docs/stealth.md](docs/stealth.md).
554
+ - [x] **Recorder (blueprint + gestes)** : création de Blueprint **par démonstration**,
555
+ **Act-agnostique** — une coquille commune (navigateur, overlay, session) + un **backend par Act**
556
+ derrière une interface unique (`recorder/base.py`, registre `act → backend`), choix de l'Act à la
557
+ main (`--act` / sélecteur Console). **Continuum** (Act II) : capture des actions DOM, **synthèse de
558
+ sélecteurs robustes** (`data-testid`/id/**href**/name/aria/classe avant le chemin CSS positionnel,
559
+ unicité mesurée in-page façon `get_by_text`), et **menu flottant** (overlay Shadow DOM) pour
560
+ **sélectionner les données** : champs, listes (`as: list`), tableaux/records (`each`/`fields`),
561
+ `wait_for`, paramétrage en `input`. **Vector** (Act I) : observe le trafic réseau (fetch/XHR/doc
562
+ JSON) et pique les champs dans la réponse → `http.request` + extraction JSONPath. Credentials et
563
+ en-têtes d'auth → `{{ secrets.x }}` (jamais stockés). Blueprint produit relu par le loader/validator
564
+ canonique, avec ses `outputs`. Console interactive + CLI (`aetherius record`). Gesture recorder
565
+ (`aetherius record-gestures`) : traces souris réelles vers la bibliothèque de discrétion. Trous
566
+ documentés pour Oracle/Phantom. Cœur pur en CI de base ; intégration Chromium réelle. Exemples :
567
+ `examples/continuum/quotes-recorded-{login,scrape}` + `examples/vector/jsonplaceholder-users-recorded`.
568
+ Détails : [docs/recorder.md](docs/recorder.md).
569
+ - [x] **Builder headless + Blueprint Studio** : construction de Blueprints **sans JSON**, réutilisable
570
+ (Console, daemon, SDK). Module `builder/` pur : `catalog` (projection du dictionnaire d'actions),
571
+ `factory` (`BlueprintDraft` lossless, `validate_draft` non-levant pour l'aperçu live,
572
+ `build`/`save`), `templates` garantis valides. Specs d'actions déclaratives dans `core/actions/`
573
+ (l'invariant « registre = source, catalogue = projection » est désormais matérialisé), gardées par
574
+ deux tests anti-drift (bijection specs↔capabilities, dispatch specs↔drivers ; `PENDING_ACTIONS`
575
+ documente les actions déclarées mais pas encore exécutées). **Blueprint Studio** dans la Console :
576
+ sélection d'Act expliquée, inputs/secrets typés, steps par formulaires (params imbriqués en JSON +
577
+ trappe « raw JSON »), options durables, **aperçu JSON validé en direct**, et **édition** d'un
578
+ Blueprint existant (Library → `e`) — round-trip lossless garanti sur tous les exemples. Sauvegarde
579
+ dans `./blueprints`. Détails : [docs/builder.md](docs/builder.md).
580
+ - [x] **Daemon local + SDK TypeScript** : daemon FastAPI (HTTP + WebSocket) exposant le moteur à tout
581
+ langage — `POST /v1/runs` (202 + `run_id`), `GET /v1/runs/{id}`, flux d'événements WebSocket (rejeu
582
+ bufferisé + live jusqu'à `done`), `POST /v1/blueprints/validate`, `GET /v1/schema`, `GET /health` ;
583
+ token bearer optionnel, bind loopback. Runs exécutés sur un thread de worker, événements relayés via
584
+ le pattern Sink (thread → asyncio). SDK TypeScript `@aetherius/client` (Node 20+) : spawn du daemon
585
+ (ou `baseUrl`), `client.run(blueprint, { inputs, secrets, onEvent })`, stream d'événements typé, avec
586
+ un E2E réel en CI. Console : l'écran **Settings** démarre/arrête le daemon. Enregistrement
587
+ volontairement host-local (`/v1/recorder/sessions` → 501). Détails : [docs/daemon.md](docs/daemon.md).
588
+
589
+ **Phase 1 terminée.** Aetherius est utilisable comme bibliothèque et comme service ; c'est le point de
590
+ contrôle prévu pour l'éprouver en conditions réelles et corriger avant la suite.
591
+
592
+ ### Phase 2 — les Acts autonomes (à venir)
593
+
594
+ - [ ] Act III — Oracle (vision + entraînement).
595
+ - [ ] Act IV — Phantom (agent).
596
+
597
+ ## Sources de référence
598
+
599
+ Ce README et [`legacy_examples/README.md`](legacy_examples/README.md) constituent la documentation
600
+ de référence complète du projet : vision, 4 Acts, format Blueprint, architecture. Les fichiers de
601
+ [`legacy_examples/`](legacy_examples/) (carte de provenance) sont les cas d'usage réels à l'origine
602
+ de chaque décision de conception.
603
+
604
+ ---
605
+
606
+ <p align="center"><sub>❧ ▚▞▚ &nbsp;✦&nbsp; per nubes, ad aethera &nbsp;✦&nbsp; ▚▞▚ ❦</sub></p>