django-lucy-assist 0.1.0__py3-none-any.whl → 1.0.2__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.
- {django_lucy_assist-0.1.0.dist-info → django_lucy_assist-1.0.2.dist-info}/METADATA +11 -20
- {django_lucy_assist-0.1.0.dist-info → django_lucy_assist-1.0.2.dist-info}/RECORD +12 -12
- lucy_assist/__init__.py +1 -1
- lucy_assist/conf.py +3 -4
- lucy_assist/migrations/0001_initial.py +24 -24
- lucy_assist/services/bug_notification_service.py +6 -1
- lucy_assist/services/claude_service.py +2 -2
- lucy_assist/services/context_service.py +9 -6
- lucy_assist/static/lucy_assist/css/lucy-assist.css +839 -79
- lucy_assist/templates/lucy_assist/chatbot_sidebar.html +191 -195
- {django_lucy_assist-0.1.0.dist-info → django_lucy_assist-1.0.2.dist-info}/WHEEL +0 -0
- {django_lucy_assist-0.1.0.dist-info → django_lucy_assist-1.0.2.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-lucy-assist
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.0.2
|
|
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>
|
|
@@ -68,11 +68,7 @@ Ajouter dans votre fichier `.env` :
|
|
|
68
68
|
|
|
69
69
|
```bash
|
|
70
70
|
# ======================================== LUCY ASSIST ========================================
|
|
71
|
-
|
|
72
|
-
ANTHROPIC_API_KEY=sk-ant-...
|
|
73
|
-
|
|
74
|
-
# Configuration GitLab pour l'analyse de bugs (optionnel)
|
|
75
|
-
GITLAB_URL=https://gitlab.example.com
|
|
71
|
+
CLAUDE_LUCY_ASSIST_API_KEY=sk-ant-...
|
|
76
72
|
GITLAB_TOKEN=glpat-...
|
|
77
73
|
GITLAB_PROJECT_ID=123
|
|
78
74
|
|
|
@@ -85,20 +81,13 @@ Puis dans votre `settings.py` :
|
|
|
85
81
|
```python
|
|
86
82
|
import os
|
|
87
83
|
|
|
84
|
+
#############################################################################################################
|
|
88
85
|
# Lucy Assist
|
|
89
|
-
|
|
90
|
-
GITLAB_URL =
|
|
91
|
-
GITLAB_TOKEN =
|
|
92
|
-
GITLAB_PROJECT_ID =
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
# Configuration avancée (optionnel)
|
|
96
|
-
LUCY_ASSIST = {
|
|
97
|
-
# Modèle de base personnalisé
|
|
98
|
-
'BASE_MODEL': 'mon_app.models.MonModeleBase',
|
|
99
|
-
# Préfixe des apps du projet pour le mapping modèle -> app
|
|
100
|
-
'PROJECT_APPS_PREFIX': 'apps.',
|
|
101
|
-
}
|
|
86
|
+
CLAUDE_LUCY_ASSIST_API_KEY = env('CLAUDE_LUCY_ASSIST_API_KEY', default=None)
|
|
87
|
+
GITLAB_URL = env('GITLAB_URL', default=None)
|
|
88
|
+
GITLAB_TOKEN = env('GITLAB_TOKEN', default=None)
|
|
89
|
+
GITLAB_PROJECT_ID = env('GITLAB_PROJECT_ID', default=None)
|
|
90
|
+
LUCY_ASSIST = {'PROJECT_APPS_PREFIX': 'apps.'}
|
|
102
91
|
```
|
|
103
92
|
|
|
104
93
|
### 3. Ajouter les URLs
|
|
@@ -197,10 +186,12 @@ Lucy Assist expose plusieurs endpoints API :
|
|
|
197
186
|
## Versionning
|
|
198
187
|
|
|
199
188
|
- V1.0.0 | Création du module Lucy
|
|
189
|
+
- V1.0.1 | Correction de bugs
|
|
190
|
+
- V1.0.2 | Correction de bugs
|
|
200
191
|
|
|
201
192
|
## Déploiement Pypi
|
|
202
193
|
|
|
203
|
-
1. `pip install build twine`
|
|
194
|
+
1. `docker-compose exec django pip install build twine`
|
|
204
195
|
2. `python -m build`
|
|
205
196
|
3. `python -m twine upload dist/*`
|
|
206
197
|
4. Indiquer le token présent dans 1Password
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
lucy_assist/__init__.py,sha256=
|
|
1
|
+
lucy_assist/__init__.py,sha256=d3z1eVP4nTVVKLa2UO5FydIpY8L-6tPlydPkLySeJ8c,335
|
|
2
2
|
lucy_assist/admin.py,sha256=-hNfuwuMfxgZVFQc_ODy6WcyZPxrM_8TfKsRMd0fj38,694
|
|
3
3
|
lucy_assist/apps.py,sha256=zHZtlBXs5ML4CKtGg7xDyptSWzLfB1ks2VvbXF50hdo,264
|
|
4
|
-
lucy_assist/conf.py,sha256=
|
|
4
|
+
lucy_assist/conf.py,sha256=xp5t-CRG4L7R-NOkb2sY6-XkmGee7M7Eb-jAVr-CAzk,3500
|
|
5
5
|
lucy_assist/constantes.py,sha256=YppDWi1DQueMwJk3jmeGPDi-UTmSUUDSwR6sW7QzBn4,4083
|
|
6
6
|
lucy_assist/context_processors.py,sha256=mDrr9G5XztDfJLGq_75X1rkJbVI5De08ys_pW3y12Dw,2210
|
|
7
7
|
lucy_assist/signals.py,sha256=aQA84oe9JNL72eeV5kURTTV-9CcQpqakDle1Lv3dnFY,861
|
|
8
8
|
lucy_assist/urls.py,sha256=Qr8jJjEyC_EFGAeiZnjhgTc-9P4Y-TqKDaYicWRp_GQ,1451
|
|
9
|
-
lucy_assist/migrations/0001_initial.py,sha256=
|
|
9
|
+
lucy_assist/migrations/0001_initial.py,sha256=Z4chOo4Ok_5VqQyHvfPS00ikyuefdwHF3LaH4SKpzoQ,4977
|
|
10
10
|
lucy_assist/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
lucy_assist/models/__init__.py,sha256=JQMr50P94sBrKwwcNArRE_qnk7dLnknMKCabeRLskJc,415
|
|
12
12
|
lucy_assist/models/base.py,sha256=Ql2AY7bzvcxZhxsPdCpbVEKvtWD-NBkHTLYZX4TjT3s,1532
|
|
@@ -15,18 +15,18 @@ lucy_assist/models/conversation.py,sha256=psx2AQtQ5SFP-AJD7wbGabpXXLIGYngdVZfeoT
|
|
|
15
15
|
lucy_assist/models/message.py,sha256=kf-ffMtLYNFhXYUrB3QSL97KKDJUOMrKaPjKeOcJa_o,1492
|
|
16
16
|
lucy_assist/models/project_context_cache.py,sha256=Bnb0VU7pv7QEvjOI6JSLEPvL4BxskCQ0ojWGxO7YDSM,6530
|
|
17
17
|
lucy_assist/services/__init__.py,sha256=I0brW674WNIKkGHj2lj4sGEDD7HUAr5Z254dsbirdLk,691
|
|
18
|
-
lucy_assist/services/bug_notification_service.py,sha256=
|
|
19
|
-
lucy_assist/services/claude_service.py,sha256=
|
|
20
|
-
lucy_assist/services/context_service.py,sha256=
|
|
18
|
+
lucy_assist/services/bug_notification_service.py,sha256=TfbjB2klvmeTkQZD-XBjnANmOSnEmPryyvjgg2PGhqk,7222
|
|
19
|
+
lucy_assist/services/claude_service.py,sha256=9eU28qGadHmUZYW3ExQZOfsH1pxcarzpYlcRhKJu3Yc,15897
|
|
20
|
+
lucy_assist/services/context_service.py,sha256=RakjdAV74GlJlLsLYiTRluTQVmnkKC92xrXgWhnYJHQ,12232
|
|
21
21
|
lucy_assist/services/crud_service.py,sha256=E8-xRxPXXbUuPakGXPsbZfImEJWZx4BZq5DhM5q2I08,11436
|
|
22
22
|
lucy_assist/services/gitlab_service.py,sha256=uH83fwRSCwiRItznENpYQG4aPckjafYIV9z6OChUrZg,8056
|
|
23
23
|
lucy_assist/services/project_context_service.py,sha256=bIuqTanc59gP_BLod3oQgWplxpiCgByg-kbUMe_57CQ,14053
|
|
24
24
|
lucy_assist/services/tool_executor_service.py,sha256=fXLH4Aaip-HPX1nNRs8UQ1N77rGloBahSwOR9gPmjfU,13583
|
|
25
25
|
lucy_assist/services/tools_definition.py,sha256=xUJCtFZ1uROxB7jNHY0X75fs5nzFAKr4VpSHtKgepxU,8974
|
|
26
|
-
lucy_assist/static/lucy_assist/css/lucy-assist.css,sha256=
|
|
26
|
+
lucy_assist/static/lucy_assist/css/lucy-assist.css,sha256=gUfj4OUTz_aFiXWau1iXtHEmfUCkUI2zGMfwkLk2nXs,18190
|
|
27
27
|
lucy_assist/static/lucy_assist/image/icon-lucy.png,sha256=FOYlwXAt40Gr9jsWFmhgPivYOBFWKeYW0lxJI5Up-GM,6710
|
|
28
28
|
lucy_assist/static/lucy_assist/js/lucy-assist.js,sha256=dmXtSPQ38LisoRWZd3R1Ms6OvVaEk3OrYKcVM0OMb_Q,28207
|
|
29
|
-
lucy_assist/templates/lucy_assist/chatbot_sidebar.html,sha256=
|
|
29
|
+
lucy_assist/templates/lucy_assist/chatbot_sidebar.html,sha256=cKyXkH3hPTxqfo42Osr__Aa9eBleI6bw0j1tGJVa0nQ,18919
|
|
30
30
|
lucy_assist/templates/lucy_assist/partials/documentation_content.html,sha256=byA2EvQT1GaMB5yTQHNt5ZfJKEew9_LxutU8s5muM9s,4143
|
|
31
31
|
lucy_assist/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
32
|
lucy_assist/tests/test_lucy_assist.py,sha256=KBvuED10_gOJWdaRS2zMigM3W5Kp00KhMEwaR8tvhUc,6949
|
|
@@ -38,7 +38,7 @@ lucy_assist/utils/message_utils.py,sha256=kABNVlfJTzmbRTVdauKPN5HVRqyw352xu_rlQr
|
|
|
38
38
|
lucy_assist/utils/token_utils.py,sha256=rxe9jHjcRJcaIlcw0QuVmYXOjscTsUsxnhhI6RMBzDM,2608
|
|
39
39
|
lucy_assist/views/__init__.py,sha256=uUPYpuHlBC8j7zKS_DDoWjwpCpRnOIXETY-S2-Ss0cY,288
|
|
40
40
|
lucy_assist/views/api_views.py,sha256=C8Ftut7qNSauzFNoZ4yPMhiADeEma7aiqrQrN9Gx9Yk,23281
|
|
41
|
-
django_lucy_assist-
|
|
42
|
-
django_lucy_assist-
|
|
43
|
-
django_lucy_assist-
|
|
44
|
-
django_lucy_assist-
|
|
41
|
+
django_lucy_assist-1.0.2.dist-info/METADATA,sha256=zCXWwX_wzpx_PTl0EtpSpB6ZLVd2gjL15FvyQVdKX44,5656
|
|
42
|
+
django_lucy_assist-1.0.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
43
|
+
django_lucy_assist-1.0.2.dist-info/top_level.txt,sha256=T-UCiwpn5yF3Oem3234TUpSVnEgbkrM2rGz9Tz5N-QA,12
|
|
44
|
+
django_lucy_assist-1.0.2.dist-info/RECORD,,
|
lucy_assist/__init__.py
CHANGED
|
@@ -5,7 +5,7 @@ Un chatbot IA basé sur Claude d'Anthropic, intégrable dans n'importe quelle
|
|
|
5
5
|
application Django pour fournir une assistance contextuelle aux utilisateurs.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
__version__ = '
|
|
8
|
+
__version__ = '1.0.2'
|
|
9
9
|
__author__ = 'Revolucy'
|
|
10
10
|
|
|
11
11
|
default_app_config = 'lucy_assist.apps.LucyAssistConfig'
|
lucy_assist/conf.py
CHANGED
|
@@ -17,8 +17,8 @@ class LucyAssistSettings:
|
|
|
17
17
|
# Peut être une string "mon_app.models.MonModele" ou une classe directement
|
|
18
18
|
'BASE_MODEL': None,
|
|
19
19
|
|
|
20
|
-
# Clé API Claude (peut aussi être définie via
|
|
21
|
-
'
|
|
20
|
+
# Clé API Claude (peut aussi être définie via CLAUDE_LUCY_ASSIST_API_KEY)
|
|
21
|
+
'CLAUDE_LUCY_ASSIST_API_KEY': None,
|
|
22
22
|
|
|
23
23
|
# Modèle Claude à utiliser
|
|
24
24
|
'CLAUDE_MODEL': 'claude-sonnet-4-20250514',
|
|
@@ -67,11 +67,10 @@ class LucyAssistSettings:
|
|
|
67
67
|
return self._settings[name]
|
|
68
68
|
|
|
69
69
|
# Cas spéciaux pour les settings qui peuvent être définis au niveau global
|
|
70
|
-
if name == '
|
|
70
|
+
if name == 'CLAUDE_LUCY_ASSIST_API_KEY':
|
|
71
71
|
# Chercher dans plusieurs variables possibles
|
|
72
72
|
return (
|
|
73
73
|
getattr(settings, 'CLAUDE_LUCY_ASSIST_API_KEY', None) or
|
|
74
|
-
getattr(settings, 'ANTHROPIC_API_KEY', None) or
|
|
75
74
|
self.DEFAULTS[name]
|
|
76
75
|
)
|
|
77
76
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# Generated
|
|
1
|
+
# Generated by Django 6.0.1 on 2026-01-26 17:03
|
|
2
2
|
|
|
3
|
+
import django.db.models.deletion
|
|
3
4
|
from django.conf import settings
|
|
4
5
|
from django.db import migrations, models
|
|
5
|
-
import django.db.models.deletion
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class Migration(migrations.Migration):
|
|
@@ -19,7 +19,7 @@ class Migration(migrations.Migration):
|
|
|
19
19
|
fields=[
|
|
20
20
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
21
21
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
|
22
|
-
('updated_date', models.DateTimeField(auto_now=True, null=True
|
|
22
|
+
('updated_date', models.DateTimeField(auto_now=True, null=True)),
|
|
23
23
|
('is_active', models.BooleanField(default=True)),
|
|
24
24
|
('tokens_disponibles', models.BigIntegerField(default=0)),
|
|
25
25
|
('prix_par_million_tokens', models.DecimalField(decimal_places=2, default=10.0, max_digits=10)),
|
|
@@ -33,12 +33,31 @@ class Migration(migrations.Migration):
|
|
|
33
33
|
'verbose_name_plural': 'Configuration Lucy Assist',
|
|
34
34
|
},
|
|
35
35
|
),
|
|
36
|
+
migrations.CreateModel(
|
|
37
|
+
name='ProjectContextCache',
|
|
38
|
+
fields=[
|
|
39
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
40
|
+
('created_date', models.DateTimeField(auto_now_add=True)),
|
|
41
|
+
('updated_date', models.DateTimeField(auto_now=True, null=True)),
|
|
42
|
+
('is_active', models.BooleanField(default=True)),
|
|
43
|
+
('cache_key', models.CharField(db_index=True, max_length=255, unique=True)),
|
|
44
|
+
('contenu', models.JSONField(default=dict)),
|
|
45
|
+
('content_hash', models.CharField(blank=True, max_length=64)),
|
|
46
|
+
('expire_at', models.DateTimeField()),
|
|
47
|
+
('tokens_economises', models.BigIntegerField(default=0)),
|
|
48
|
+
('hit_count', models.IntegerField(default=0)),
|
|
49
|
+
],
|
|
50
|
+
options={
|
|
51
|
+
'verbose_name': 'Cache contexte projet',
|
|
52
|
+
'verbose_name_plural': 'Caches contexte projet',
|
|
53
|
+
},
|
|
54
|
+
),
|
|
36
55
|
migrations.CreateModel(
|
|
37
56
|
name='Conversation',
|
|
38
57
|
fields=[
|
|
39
58
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
40
59
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
|
41
|
-
('updated_date', models.DateTimeField(auto_now=True, null=True
|
|
60
|
+
('updated_date', models.DateTimeField(auto_now=True, null=True)),
|
|
42
61
|
('is_active', models.BooleanField(default=True)),
|
|
43
62
|
('titre', models.CharField(blank=True, max_length=255, null=True)),
|
|
44
63
|
('page_contexte', models.CharField(blank=True, max_length=500, null=True)),
|
|
@@ -55,7 +74,7 @@ class Migration(migrations.Migration):
|
|
|
55
74
|
fields=[
|
|
56
75
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
57
76
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
|
58
|
-
('updated_date', models.DateTimeField(auto_now=True, null=True
|
|
77
|
+
('updated_date', models.DateTimeField(auto_now=True, null=True)),
|
|
59
78
|
('is_active', models.BooleanField(default=True)),
|
|
60
79
|
('repondant', models.CharField(choices=[('UTILISATEUR', 'Utilisateur'), ('CHATBOT', 'Lucy Assist')], max_length=20)),
|
|
61
80
|
('contenu', models.TextField()),
|
|
@@ -70,23 +89,4 @@ class Migration(migrations.Migration):
|
|
|
70
89
|
'ordering': ['created_date'],
|
|
71
90
|
},
|
|
72
91
|
),
|
|
73
|
-
migrations.CreateModel(
|
|
74
|
-
name='ProjectContextCache',
|
|
75
|
-
fields=[
|
|
76
|
-
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
77
|
-
('created_date', models.DateTimeField(auto_now_add=True)),
|
|
78
|
-
('updated_date', models.DateTimeField(auto_now=True, null=True, blank=True)),
|
|
79
|
-
('is_active', models.BooleanField(default=True)),
|
|
80
|
-
('cache_key', models.CharField(db_index=True, max_length=255, unique=True)),
|
|
81
|
-
('contenu', models.JSONField(default=dict)),
|
|
82
|
-
('content_hash', models.CharField(blank=True, max_length=64)),
|
|
83
|
-
('expire_at', models.DateTimeField()),
|
|
84
|
-
('tokens_economises', models.BigIntegerField(default=0)),
|
|
85
|
-
('hit_count', models.IntegerField(default=0)),
|
|
86
|
-
],
|
|
87
|
-
options={
|
|
88
|
-
'verbose_name': 'Cache contexte projet',
|
|
89
|
-
'verbose_name_plural': 'Caches contexte projet',
|
|
90
|
-
},
|
|
91
|
-
),
|
|
92
92
|
]
|
|
@@ -153,10 +153,15 @@ suite à la détection d'un bug lors de l'analyse du code via GitLab.
|
|
|
153
153
|
================================================================================
|
|
154
154
|
"""
|
|
155
155
|
|
|
156
|
+
# Récupérer l'email expéditeur avec fallback
|
|
157
|
+
from_email = getattr(settings, 'EMAIL_EXPEDITEUR', None) \
|
|
158
|
+
or getattr(settings, 'DEFAULT_FROM_EMAIL', None) \
|
|
159
|
+
or 'noreply@revolucy.fr'
|
|
160
|
+
|
|
156
161
|
send_mail(
|
|
157
162
|
subject=sujet,
|
|
158
163
|
message=message_email,
|
|
159
|
-
from_email=
|
|
164
|
+
from_email=from_email,
|
|
160
165
|
recipient_list=[destinataire],
|
|
161
166
|
fail_silently=False
|
|
162
167
|
)
|
|
@@ -31,9 +31,9 @@ class ClaudeService:
|
|
|
31
31
|
MAX_CONTEXT_TOKENS = 2000 # Limiter le contexte à 2000 tokens estimés
|
|
32
32
|
|
|
33
33
|
def __init__(self):
|
|
34
|
-
self.api_key = lucy_assist_settings.
|
|
34
|
+
self.api_key = lucy_assist_settings.CLAUDE_LUCY_ASSIST_API_KEY
|
|
35
35
|
if not self.api_key:
|
|
36
|
-
raise ValueError("
|
|
36
|
+
raise ValueError("CLAUDE_LUCY_ASSIST_API_KEY non configurée dans les settings")
|
|
37
37
|
|
|
38
38
|
self.client = anthropic.Anthropic(api_key=self.api_key)
|
|
39
39
|
self._project_context_service = None
|
|
@@ -299,12 +299,15 @@ class ContextService:
|
|
|
299
299
|
for field_name in search_fields[:5]: # Limiter à 5 champs
|
|
300
300
|
q_objects |= Q(**{f'{field_name}__icontains': query})
|
|
301
301
|
|
|
302
|
-
# Filtrer par permissions si
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
302
|
+
# Filtrer par permissions si possible
|
|
303
|
+
# Note: certains modèles utilisent des managers customs qui
|
|
304
|
+
# dépendent de ThreadLocal/middleware pour l'utilisateur courant
|
|
305
|
+
try:
|
|
306
|
+
queryset = model.objects.all()
|
|
307
|
+
objects = queryset.filter(q_objects)[:limit]
|
|
308
|
+
except AttributeError:
|
|
309
|
+
# Si le manager a besoin d'un utilisateur non disponible, skip ce modèle
|
|
310
|
+
continue
|
|
308
311
|
|
|
309
312
|
for obj in objects:
|
|
310
313
|
result = {
|