django-lucy-assist 1.2.0__tar.gz → 1.2.1__tar.gz

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 (54) hide show
  1. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/PKG-INFO +1 -1
  2. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/django_lucy_assist.egg-info/PKG-INFO +1 -1
  3. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/django_lucy_assist.egg-info/SOURCES.txt +1 -0
  4. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/__init__.py +1 -1
  5. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/conf.py +4 -0
  6. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/constantes.py +6 -30
  7. django_lucy_assist-1.2.1/lucy_assist/migrations/0004_configurationlucyassist_system_prompt.py +22 -0
  8. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/models/configuration.py +93 -2
  9. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/services/mistral_service.py +13 -11
  10. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/services/project_context_service.py +32 -15
  11. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/signals.py +17 -0
  12. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/pyproject.toml +1 -1
  13. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/MANIFEST.in +0 -0
  14. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/README.md +0 -0
  15. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/django_lucy_assist.egg-info/dependency_links.txt +0 -0
  16. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/django_lucy_assist.egg-info/requires.txt +0 -0
  17. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/django_lucy_assist.egg-info/top_level.txt +0 -0
  18. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/admin.py +0 -0
  19. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/apps.py +0 -0
  20. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/context_processors.py +0 -0
  21. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/migrations/0001_initial.py +0 -0
  22. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/migrations/0002_configurationlucyassist_prompt_complementaire.py +0 -0
  23. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/migrations/0003_configurationlucyassist_crud_views_mapping.py +0 -0
  24. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/migrations/__init__.py +0 -0
  25. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/models/__init__.py +0 -0
  26. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/models/base.py +0 -0
  27. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/models/conversation.py +0 -0
  28. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/models/message.py +0 -0
  29. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/models/project_context_cache.py +0 -0
  30. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/services/__init__.py +0 -0
  31. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/services/bug_notification_service.py +0 -0
  32. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/services/context_service.py +0 -0
  33. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/services/crud_service.py +0 -0
  34. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/services/gitlab_service.py +0 -0
  35. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/services/tool_executor_service.py +0 -0
  36. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/services/tools_definition.py +0 -0
  37. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/services/view_discovery_service.py +0 -0
  38. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/static/lucy_assist/css/lucy-assist.css +0 -0
  39. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/static/lucy_assist/image/icon-lucy.png +0 -0
  40. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/static/lucy_assist/js/lucy-assist.js +0 -0
  41. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/templates/lucy_assist/chatbot_sidebar.html +0 -0
  42. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/templates/lucy_assist/partials/documentation_content.html +0 -0
  43. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/tests/__init__.py +0 -0
  44. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/tests/factories/__init__.py +0 -0
  45. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/tests/factories/lucy_assist_factories.py +0 -0
  46. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/tests/test_lucy_assist.py +0 -0
  47. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/urls.py +0 -0
  48. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/utils/__init__.py +0 -0
  49. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/utils/log_utils.py +0 -0
  50. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/utils/message_utils.py +0 -0
  51. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/utils/token_utils.py +0 -0
  52. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/views/__init__.py +0 -0
  53. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/lucy_assist/views/api_views.py +0 -0
  54. {django_lucy_assist-1.2.0 → django_lucy_assist-1.2.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-lucy-assist
3
- Version: 1.2.0
3
+ Version: 1.2.1
4
4
  Summary: Assistant IA intelligent Revolucy pour outil métier
5
5
  Author-email: Revolucy <hello@revolucy.fr>
6
6
  Maintainer-email: Maxence <hello@revolucy.fr>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-lucy-assist
3
- Version: 1.2.0
3
+ Version: 1.2.1
4
4
  Summary: Assistant IA intelligent Revolucy pour outil métier
5
5
  Author-email: Revolucy <hello@revolucy.fr>
6
6
  Maintainer-email: Maxence <hello@revolucy.fr>
@@ -17,6 +17,7 @@ lucy_assist/urls.py
17
17
  lucy_assist/migrations/0001_initial.py
18
18
  lucy_assist/migrations/0002_configurationlucyassist_prompt_complementaire.py
19
19
  lucy_assist/migrations/0003_configurationlucyassist_crud_views_mapping.py
20
+ lucy_assist/migrations/0004_configurationlucyassist_system_prompt.py
20
21
  lucy_assist/migrations/__init__.py
21
22
  lucy_assist/models/__init__.py
22
23
  lucy_assist/models/base.py
@@ -5,7 +5,7 @@ Un chatbot IA base sur Mistral AI, integrable dans n'importe quelle
5
5
  application Django pour fournir une assistance contextuelle aux utilisateurs.
6
6
  """
7
7
 
8
- __version__ = '1.2.0'
8
+ __version__ = '1.2.1'
9
9
  __author__ = 'Revolucy'
10
10
 
11
11
  default_app_config = 'lucy_assist.apps.LucyAssistConfig'
@@ -17,6 +17,10 @@ class LucyAssistSettings:
17
17
  # Peut etre une string "mon_app.models.MonModele" ou une classe directement
18
18
  'BASE_MODEL': None,
19
19
 
20
+ # Nom de l'application (affiche dans le prompt systeme)
21
+ # Ex: 'Mon Application'
22
+ 'APPLICATION_NAME': 'cette application',
23
+
20
24
  # Cle API Mistral (peut aussi etre definie via MISTRAL_LUCY_API_KEY)
21
25
  'MISTRAL_LUCY_API_KEY': None,
22
26
 
@@ -53,7 +53,7 @@ class LucyAssistConstantes:
53
53
 
54
54
  # Prompts systeme pour Mistral
55
55
  SYSTEM_PROMPTS = {
56
- 'default': """Tu es Lucy, un assistant IA intégré dans un CRM métier (UNAF-CRM).
56
+ 'default': """Tu es Lucy, un assistant IA intégré dans l'application {application_name}.
57
57
  Tu as la capacité d'EXÉCUTER des actions directement dans l'application grâce aux tools disponibles.
58
58
 
59
59
  ## COMPORTEMENT PRIORITAIRE - ACTION FIRST
@@ -64,17 +64,6 @@ tu dois EXÉCUTER L'ACTION IMMÉDIATEMENT en utilisant les tools disponibles.
64
64
  ❌ NE FAIS PAS : Expliquer comment faire, rediriger vers une page, dire que tu ne peux pas
65
65
  ✅ FAIS : Utiliser le tool approprié pour exécuter l'action demandée
66
66
 
67
- ## Exemples de comportement attendu
68
-
69
- Utilisateur : "Crée un membre Maxence Dupont"
70
- → Tu utilises le tool create_object avec les données {{"nom": "Dupont", "prenom": "Maxence"}}
71
-
72
- Utilisateur : "Cherche les membres de Paris"
73
- → Tu utilises le tool search_objects avec query="Paris" et model_name="Membre"
74
-
75
- Utilisateur : "Modifie l'adresse du membre 42"
76
- → Tu utilises le tool update_object avec l'object_id et les nouvelles données
77
-
78
67
  ## Quand NE PAS agir directement
79
68
 
80
69
  - Si l'utilisateur demande explicitement "comment faire" ou "explique-moi"
@@ -93,32 +82,19 @@ Pour TOUTE demande de suppression, tu DOIS suivre cette procédure :
93
82
  3. Demande une confirmation EXPLICITE à l'utilisateur ("Confirmez-vous la suppression ?")
94
83
  4. SEULEMENT si l'utilisateur confirme explicitement (oui, ok, confirme, etc.), utilise `delete_object` avec `confirmed: true`
95
84
 
96
- Exemple de réponse après get_deletion_impact :
97
- "Voici les conséquences de la suppression du Client #42 :
98
- - 5 Réservations seront supprimées en cascade
99
- - 3 Paiements seront supprimés en cascade
100
- - 2 Documents auront leur champ 'client' mis à NULL
101
-
102
- **Confirmez-vous vouloir supprimer ce client et tous les éléments associés ?**"
103
-
104
85
  ## Contexte de la page actuelle
105
86
  {page_context}
106
87
 
107
88
  ## Permissions de l'utilisateur
108
89
  {user_permissions}
109
90
 
110
- ## Modèles principaux disponibles
111
- - Membre (membre) : nom, prenom, email, telephone, adresse, structure
112
- - Structure (structure) : nom, adresse, type, siret
113
- - Adhesion (adhesion) : membre, structure, date_debut, date_fin, montant
114
- - Paiement (paiement) : membre, montant, date, mode_paiement
91
+ ## Modèles disponibles dans l'application
92
+ {available_models}
115
93
 
116
94
  ## Format de réponse après action
117
95
 
118
96
  Après avoir exécuté une action, confirme brièvement :
119
97
  "✅ [Action effectuée] - [Détail bref]"
120
-
121
- Exemple : "✅ Membre créé - Maxence Dupont (ID: 123)"
122
98
  """,
123
99
  'crud': """Tu dois aider l'utilisateur à créer ou modifier un objet.
124
100
  Formulaire disponible : {form_info}
@@ -132,9 +108,9 @@ Erreur rapportée : {error_message}
132
108
 
133
109
  # Questions fréquentes par défaut (utilisées si non configurées dans le modèle)
134
110
  QUESTIONS_FREQUENTES_DEFAULT = [
135
- "Comment créer un nouveau membre ?",
136
- "Comment effectuer un paiement ?",
111
+ "Comment créer un nouvel enregistrement ?",
112
+ "Comment effectuer une recherche ?",
137
113
  "Comment exporter des données ?",
138
114
  "Comment modifier mon profil ?",
139
- " trouver la liste des adhésions ?",
115
+ "Quelles sont les fonctionnalités disponibles ?",
140
116
  ]
@@ -0,0 +1,22 @@
1
+ # Generated by Django
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('lucy_assist', '0003_configurationlucyassist_crud_views_mapping'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='configurationlucyassist',
15
+ name='system_prompt',
16
+ field=models.TextField(
17
+ blank=True,
18
+ default='',
19
+ help_text="Prompt système pour l'assistant IA. Initialisé automatiquement si vide."
20
+ ),
21
+ ),
22
+ ]
@@ -20,8 +20,16 @@ class ConfigurationLucyAssist(LucyAssistBaseModel):
20
20
  actif = models.BooleanField(default=True)
21
21
  avatar = models.ImageField(null=True, blank=True)
22
22
 
23
- # Instructions complémentaires pour le prompt
24
- prompt_complementaire = models.TextField(blank=True,default='')
23
+ # Prompt système principal pour l'assistant
24
+ # Initialisé automatiquement via signal si vide
25
+ system_prompt = models.TextField(
26
+ blank=True,
27
+ default='',
28
+ help_text="Prompt système pour l'assistant IA. Initialisé automatiquement si vide."
29
+ )
30
+
31
+ # Instructions complémentaires pour le prompt (ajoutées après le system_prompt)
32
+ prompt_complementaire = models.TextField(blank=True, default='')
25
33
 
26
34
  # Mapping des modèles vers leurs applications Django
27
35
  model_app_mapping = models.JSONField(blank=True, default=dict)
@@ -222,6 +230,89 @@ class ConfigurationLucyAssist(LucyAssistBaseModel):
222
230
  config = cls.get_config()
223
231
  return config.get_app_for_model(model_name)
224
232
 
233
+ def get_system_prompt(
234
+ self,
235
+ page_context: str = "",
236
+ user_permissions: str = "",
237
+ available_models: str = ""
238
+ ) -> str:
239
+ """
240
+ Retourne le prompt système formaté avec les variables de contexte.
241
+
242
+ Args:
243
+ page_context: Contexte JSON de la page actuelle
244
+ user_permissions: Liste des permissions de l'utilisateur
245
+ available_models: Liste des modèles disponibles
246
+
247
+ Returns:
248
+ Prompt système complet avec le prompt_complementaire ajouté
249
+ """
250
+ prompt = self.system_prompt
251
+
252
+ # Remplacer les placeholders
253
+ prompt = prompt.format(
254
+ application_name=self._get_application_name(),
255
+ page_context=page_context,
256
+ user_permissions=user_permissions,
257
+ available_models=available_models
258
+ )
259
+
260
+ # Ajouter les instructions complémentaires si configurées
261
+ if self.prompt_complementaire:
262
+ prompt += f"\n\n## Instructions complémentaires\n{self.prompt_complementaire}"
263
+
264
+ return prompt
265
+
266
+ def _get_application_name(self) -> str:
267
+ """
268
+ Retourne le nom de l'application depuis les settings.
269
+ """
270
+ return lucy_assist_settings.get('APPLICATION_NAME', 'cette application')
271
+
272
+ def get_available_models_description(self) -> str:
273
+ """
274
+ Génère dynamiquement la description des modèles disponibles
275
+ à partir des modèles Django enregistrés.
276
+
277
+ Returns:
278
+ Description formatée des modèles avec leurs champs principaux
279
+ """
280
+ from django.apps import apps
281
+
282
+ descriptions = []
283
+ apps_prefix = lucy_assist_settings.PROJECT_APPS_PREFIX
284
+
285
+ for app_config in apps.get_app_configs():
286
+ # Filtrer les apps si un préfixe est configuré
287
+ if apps_prefix and not app_config.name.startswith(apps_prefix):
288
+ continue
289
+
290
+ # Ignorer les apps Django internes et lucy_assist
291
+ if app_config.name.startswith('django.') or app_config.name == 'lucy_assist':
292
+ continue
293
+
294
+ for model in app_config.get_models():
295
+ model_name = model.__name__
296
+ model_name_lower = model_name.lower()
297
+
298
+ # Récupérer les champs principaux (exclure les champs auto)
299
+ fields = []
300
+ for field in model._meta.get_fields():
301
+ if hasattr(field, 'name') and not field.name.startswith('_'):
302
+ if hasattr(field, 'auto_created') and field.auto_created:
303
+ continue
304
+ if field.name in ('id', 'pk', 'created_at', 'updated_at'):
305
+ continue
306
+ fields.append(field.name)
307
+
308
+ if fields:
309
+ fields_str = ", ".join(fields[:8]) # Limiter à 8 champs
310
+ if len(fields) > 8:
311
+ fields_str += ", ..."
312
+ descriptions.append(f"- {model_name} ({model_name_lower}) : {fields_str}")
313
+
314
+ return "\n".join(descriptions) if descriptions else "Aucun modèle configuré"
315
+
225
316
 
226
317
  def get_default_model_app_mapping() -> dict:
227
318
  """
@@ -57,8 +57,8 @@ class MistralService:
57
57
  """
58
58
  Construit le prompt systeme avec le contexte optimise.
59
59
 
60
- Utilise le cache pour reduire la redondance des informations
61
- sur le projet.
60
+ Utilise le prompt stocke en base de donnees et le cache
61
+ pour reduire la redondance des informations sur le projet.
62
62
  """
63
63
  # Recuperer les permissions utilisateur (compressees)
64
64
  user_permissions = []
@@ -81,17 +81,19 @@ class MistralService:
81
81
  'cache_stats': optimized_context.get('stats', {})
82
82
  }
83
83
 
84
- # Construire le prompt avec contexte compact
85
- prompt = LucyAssistConstantes.SYSTEM_PROMPTS['default'].format(
86
- page_context=json.dumps(enriched_context, ensure_ascii=False, indent=2),
87
- user_permissions=', '.join(user_permissions)
88
- )
89
-
90
- # Ajouter les instructions complementaires si configurees
84
+ # Recuperer la configuration avec le prompt systeme
91
85
  from lucy_assist.models import ConfigurationLucyAssist
92
86
  config = ConfigurationLucyAssist.get_config()
93
- if config.prompt_complementaire:
94
- prompt += f"\n\n## Instructions complementaires\n{config.prompt_complementaire}"
87
+
88
+ # Generer la description des modeles disponibles
89
+ available_models = config.get_available_models_description()
90
+
91
+ # Construire le prompt depuis la configuration
92
+ prompt = config.get_system_prompt(
93
+ page_context=json.dumps(enriched_context, ensure_ascii=False, indent=2),
94
+ user_permissions=', '.join(user_permissions),
95
+ available_models=available_models
96
+ )
95
97
 
96
98
  return prompt
97
99
 
@@ -332,23 +332,40 @@ class ProjectContextService:
332
332
  return None
333
333
 
334
334
  def _detect_model_from_question(self, question: str) -> Optional[str]:
335
- """Détecte si la question mentionne un modèle."""
336
- # Mots-clés courants et leurs modèles associés
337
- model_keywords = {
338
- 'membre': 'Membre',
339
- 'adhésion': 'Adhesion',
340
- 'cotisation': 'Cotisation',
341
- 'utilisateur': 'Utilisateur',
342
- 'user': 'Utilisateur',
343
- 'paiement': 'Paiement',
344
- 'facture': 'Facture',
345
- 'structure': 'Structure',
346
- }
335
+ """
336
+ Détecte si la question mentionne un modèle.
337
+
338
+ Utilise la liste dynamique des modèles Django enregistrés
339
+ au lieu d'une liste hardcodée.
340
+ """
341
+ from django.apps import apps
342
+ from lucy_assist.conf import lucy_assist_settings
347
343
 
348
344
  question_lower = question.lower()
349
- for keyword, model in model_keywords.items():
350
- if keyword in question_lower:
351
- return model
345
+ apps_prefix = lucy_assist_settings.PROJECT_APPS_PREFIX
346
+
347
+ for app_config in apps.get_app_configs():
348
+ # Filtrer les apps si un préfixe est configuré
349
+ if apps_prefix and not app_config.name.startswith(apps_prefix):
350
+ continue
351
+
352
+ # Ignorer les apps Django internes et lucy_assist
353
+ if app_config.name.startswith('django.') or app_config.name == 'lucy_assist':
354
+ continue
355
+
356
+ for model in app_config.get_models():
357
+ model_name = model.__name__
358
+ model_name_lower = model_name.lower()
359
+
360
+ # Vérifier si le nom du modèle apparaît dans la question
361
+ if model_name_lower in question_lower:
362
+ return model_name
363
+
364
+ # Vérifier aussi le verbose_name si disponible
365
+ if hasattr(model._meta, 'verbose_name'):
366
+ verbose_name = str(model._meta.verbose_name).lower()
367
+ if verbose_name in question_lower:
368
+ return model_name
352
369
 
353
370
  return None
354
371
 
@@ -5,6 +5,7 @@ from django.db.models.signals import post_save, pre_delete
5
5
  from django.dispatch import receiver
6
6
 
7
7
  from lucy_assist.models import Message, ConfigurationLucyAssist
8
+ from lucy_assist.constantes import LucyAssistConstantes
8
9
 
9
10
 
10
11
  @receiver(post_save, sender=Message)
@@ -23,3 +24,19 @@ def message_post_save(sender, instance, created, **kwargs):
23
24
  config.tokens_disponibles = max(0, config.tokens_disponibles - instance.tokens_utilises)
24
25
  config._skip_signals = True
25
26
  config.save(update_fields=['tokens_disponibles'])
27
+
28
+
29
+ @receiver(post_save, sender=ConfigurationLucyAssist)
30
+ def config_post_save(sender, instance, created, **kwargs):
31
+ """
32
+ Signal déclenché après sauvegarde de la configuration.
33
+ Initialise le system_prompt avec le prompt par défaut si vide.
34
+ """
35
+ if getattr(instance, '_skip_signals', False):
36
+ return
37
+
38
+ if not instance.system_prompt:
39
+ # Initialiser avec le prompt par défaut
40
+ instance.system_prompt = LucyAssistConstantes.SYSTEM_PROMPTS['default']
41
+ instance._skip_signals = True
42
+ instance.save(update_fields=['system_prompt'])
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "django-lucy-assist"
7
- version = "1.2.0"
7
+ version = "1.2.1"
8
8
  description = "Assistant IA intelligent Revolucy pour outil métier"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}