django-lucy-assist 1.2.3__py3-none-any.whl → 1.2.4__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-1.2.3.dist-info → django_lucy_assist-1.2.4.dist-info}/METADATA +1 -1
- django_lucy_assist-1.2.4.dist-info/RECORD +45 -0
- lucy_assist/__init__.py +1 -1
- lucy_assist/admin.py +6 -39
- lucy_assist/conf.py +4 -0
- lucy_assist/constantes.py +79 -29
- lucy_assist/migrations/0001_initial.py +3 -1
- lucy_assist/models/configuration.py +0 -116
- lucy_assist/services/context_service.py +234 -0
- lucy_assist/services/crud_service.py +97 -13
- lucy_assist/services/gitlab_service.py +79 -6
- lucy_assist/services/mistral_service.py +31 -11
- lucy_assist/services/tool_executor_service.py +91 -0
- lucy_assist/services/tools_definition.py +65 -0
- lucy_assist/services/view_discovery_service.py +47 -13
- lucy_assist/static/lucy_assist/css/lucy-assist.css +48 -1
- lucy_assist/static/lucy_assist/js/lucy-assist.js +11 -0
- lucy_assist/templates/lucy_assist/chatbot_sidebar.html +11 -1
- django_lucy_assist-1.2.3.dist-info/RECORD +0 -50
- lucy_assist/migrations/0002_configurationlucyassist_prompt_complementaire.py +0 -18
- lucy_assist/migrations/0003_configurationlucyassist_crud_views_mapping.py +0 -18
- lucy_assist/migrations/0004_configurationlucyassist_system_prompt.py +0 -22
- lucy_assist/migrations/0005_configurationlucyassist_project_context.py +0 -22
- lucy_assist/migrations/0006_remove_configurationlucyassist_prompt_complementaire.py +0 -17
- {django_lucy_assist-1.2.3.dist-info → django_lucy_assist-1.2.4.dist-info}/WHEEL +0 -0
- {django_lucy_assist-1.2.3.dist-info → django_lucy_assist-1.2.4.dist-info}/top_level.txt +0 -0
|
@@ -54,6 +54,9 @@ class ToolExecutorService:
|
|
|
54
54
|
'get_form_fields': self._handle_get_form_fields,
|
|
55
55
|
'navigate_to_page': self._handle_navigate_to_page,
|
|
56
56
|
'analyze_bug': self._handle_analyze_bug,
|
|
57
|
+
'get_page_help': self._handle_get_page_help,
|
|
58
|
+
'search_code_gitlab': self._handle_search_code_gitlab,
|
|
59
|
+
'get_file_content_gitlab': self._handle_get_file_content_gitlab,
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
handler = handlers.get(tool_name)
|
|
@@ -371,6 +374,94 @@ class ToolExecutorService:
|
|
|
371
374
|
}
|
|
372
375
|
|
|
373
376
|
|
|
377
|
+
def _handle_get_page_help(self, params: Dict) -> Dict:
|
|
378
|
+
"""
|
|
379
|
+
Recupere l'aide contextuelle pour la page actuelle.
|
|
380
|
+
"""
|
|
381
|
+
url_path = params.get('url_path', '')
|
|
382
|
+
|
|
383
|
+
if not url_path:
|
|
384
|
+
return {'error': 'url_path est requis'}
|
|
385
|
+
|
|
386
|
+
help_info = self.context_service.get_page_help(url_path)
|
|
387
|
+
|
|
388
|
+
return {
|
|
389
|
+
'success': True,
|
|
390
|
+
**help_info
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
def _handle_search_code_gitlab(self, params: Dict) -> Dict:
|
|
394
|
+
"""
|
|
395
|
+
Recherche dans le code source du projet via GitLab.
|
|
396
|
+
"""
|
|
397
|
+
query = params.get('query', '')
|
|
398
|
+
file_type = params.get('file_type', 'all')
|
|
399
|
+
|
|
400
|
+
if not query:
|
|
401
|
+
return {'error': 'query est requis'}
|
|
402
|
+
|
|
403
|
+
# Adapter la recherche selon le type de fichier
|
|
404
|
+
search_query = query
|
|
405
|
+
if file_type != 'all':
|
|
406
|
+
# Ajouter un filtre de chemin pour cibler le type de fichier
|
|
407
|
+
search_query = f"{query} path:{file_type}"
|
|
408
|
+
|
|
409
|
+
results = self.gitlab_service.search_code(search_query, per_page=10)
|
|
410
|
+
|
|
411
|
+
if not results:
|
|
412
|
+
return {
|
|
413
|
+
'success': True,
|
|
414
|
+
'count': 0,
|
|
415
|
+
'message': f'Aucun resultat trouve pour "{query}"',
|
|
416
|
+
'results': []
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
# Formater les resultats
|
|
420
|
+
formatted_results = []
|
|
421
|
+
for result in results[:10]:
|
|
422
|
+
formatted_results.append({
|
|
423
|
+
'file': result.get('filename', ''),
|
|
424
|
+
'content_preview': result.get('data', '')[:500],
|
|
425
|
+
'ref': result.get('ref', '')
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
return {
|
|
429
|
+
'success': True,
|
|
430
|
+
'count': len(formatted_results),
|
|
431
|
+
'query': query,
|
|
432
|
+
'results': formatted_results
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
def _handle_get_file_content_gitlab(self, params: Dict) -> Dict:
|
|
436
|
+
"""
|
|
437
|
+
Recupere le contenu complet d'un fichier depuis GitLab.
|
|
438
|
+
"""
|
|
439
|
+
file_path = params.get('file_path', '')
|
|
440
|
+
|
|
441
|
+
if not file_path:
|
|
442
|
+
return {'error': 'file_path est requis'}
|
|
443
|
+
|
|
444
|
+
content = self.gitlab_service.get_file_content(file_path)
|
|
445
|
+
|
|
446
|
+
if content is None:
|
|
447
|
+
return {
|
|
448
|
+
'success': False,
|
|
449
|
+
'error': f'Fichier non trouve: {file_path}'
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
# Limiter la taille du contenu retourne
|
|
453
|
+
max_content_size = 10000
|
|
454
|
+
truncated = len(content) > max_content_size
|
|
455
|
+
|
|
456
|
+
return {
|
|
457
|
+
'success': True,
|
|
458
|
+
'file_path': file_path,
|
|
459
|
+
'content': content[:max_content_size],
|
|
460
|
+
'truncated': truncated,
|
|
461
|
+
'total_size': len(content)
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
|
|
374
465
|
def create_tool_executor(user):
|
|
375
466
|
"""
|
|
376
467
|
Factory function pour créer un callable d'exécution de tools.
|
|
@@ -274,6 +274,71 @@ LUCY_ASSIST_TOOLS = [
|
|
|
274
274
|
"required": ["user_description"]
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
"type": "function",
|
|
280
|
+
"function": {
|
|
281
|
+
"name": "get_page_help",
|
|
282
|
+
"description": """Recupere l'aide contextuelle pour la page actuelle.
|
|
283
|
+
Utilise ce tool pour obtenir des informations sur ce que l'utilisateur peut faire sur la page.
|
|
284
|
+
Retourne les actions suggerees, liens utiles et conseils.""",
|
|
285
|
+
"parameters": {
|
|
286
|
+
"type": "object",
|
|
287
|
+
"properties": {
|
|
288
|
+
"url_path": {
|
|
289
|
+
"type": "string",
|
|
290
|
+
"description": "URL de la page actuelle (disponible dans le contexte)"
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
"required": ["url_path"]
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"type": "function",
|
|
299
|
+
"function": {
|
|
300
|
+
"name": "search_code_gitlab",
|
|
301
|
+
"description": """USAGE INTERNE - Recherche dans le code source pour comprendre le fonctionnement.
|
|
302
|
+
Utilise ce tool pour comprendre comment fonctionne une fonctionnalite.
|
|
303
|
+
IMPORTANT: Les resultats sont pour TON usage interne uniquement.
|
|
304
|
+
Ne JAMAIS montrer les chemins de fichiers ou le code a l'utilisateur.
|
|
305
|
+
Utilise ces informations pour repondre en termes simples avec des liens vers les pages.""",
|
|
306
|
+
"parameters": {
|
|
307
|
+
"type": "object",
|
|
308
|
+
"properties": {
|
|
309
|
+
"query": {
|
|
310
|
+
"type": "string",
|
|
311
|
+
"description": "Terme de recherche (nom de classe, fonction, variable, texte)"
|
|
312
|
+
},
|
|
313
|
+
"file_type": {
|
|
314
|
+
"type": "string",
|
|
315
|
+
"enum": ["models", "views", "urls", "forms", "admin", "all"],
|
|
316
|
+
"description": "Type de fichier a rechercher (defaut: all)"
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
"required": ["query"]
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
"type": "function",
|
|
325
|
+
"function": {
|
|
326
|
+
"name": "get_file_content_gitlab",
|
|
327
|
+
"description": """USAGE INTERNE - Recupere le contenu d'un fichier pour comprendre le fonctionnement.
|
|
328
|
+
IMPORTANT: Les resultats sont pour TON usage interne uniquement.
|
|
329
|
+
Ne JAMAIS montrer le code source ou les chemins de fichiers a l'utilisateur.
|
|
330
|
+
Utilise ces informations pour repondre en termes simples avec des liens vers les pages.""",
|
|
331
|
+
"parameters": {
|
|
332
|
+
"type": "object",
|
|
333
|
+
"properties": {
|
|
334
|
+
"file_path": {
|
|
335
|
+
"type": "string",
|
|
336
|
+
"description": "Chemin du fichier dans le repository"
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
"required": ["file_path"]
|
|
340
|
+
}
|
|
341
|
+
}
|
|
277
342
|
}
|
|
278
343
|
]
|
|
279
344
|
|
|
@@ -16,8 +16,16 @@ from lucy_assist.conf import lucy_assist_settings
|
|
|
16
16
|
class ViewDiscoveryService:
|
|
17
17
|
"""
|
|
18
18
|
Service pour découvrir automatiquement les vues CRUD d'un projet Django.
|
|
19
|
+
|
|
20
|
+
La découverte est mise en cache en mémoire pour éviter de scanner
|
|
21
|
+
les URLs à chaque requête.
|
|
19
22
|
"""
|
|
20
23
|
|
|
24
|
+
# Cache en mémoire pour les vues découvertes (partagé entre instances)
|
|
25
|
+
_views_cache = None
|
|
26
|
+
_cache_timestamp = None
|
|
27
|
+
CACHE_TTL = 300 # 5 minutes
|
|
28
|
+
|
|
21
29
|
# Patterns de nommage courants pour les vues CRUD
|
|
22
30
|
# L'ordre est important : les patterns plus spécifiques doivent être en premier
|
|
23
31
|
CRUD_PATTERNS = {
|
|
@@ -65,6 +73,35 @@ class ViewDiscoveryService:
|
|
|
65
73
|
def __init__(self):
|
|
66
74
|
self.apps_prefix = lucy_assist_settings.PROJECT_APPS_PREFIX or ''
|
|
67
75
|
|
|
76
|
+
@classmethod
|
|
77
|
+
def get_cached_views(cls) -> Dict:
|
|
78
|
+
"""
|
|
79
|
+
Retourne les vues CRUD depuis le cache mémoire.
|
|
80
|
+
Redécouvre automatiquement si le cache est expiré.
|
|
81
|
+
"""
|
|
82
|
+
import time
|
|
83
|
+
|
|
84
|
+
now = time.time()
|
|
85
|
+
|
|
86
|
+
# Vérifier si le cache est valide
|
|
87
|
+
if (cls._views_cache is not None and
|
|
88
|
+
cls._cache_timestamp is not None and
|
|
89
|
+
now - cls._cache_timestamp < cls.CACHE_TTL):
|
|
90
|
+
return cls._views_cache
|
|
91
|
+
|
|
92
|
+
# Redécouvrir les vues
|
|
93
|
+
service = cls()
|
|
94
|
+
cls._views_cache = service.discover_crud_views()
|
|
95
|
+
cls._cache_timestamp = now
|
|
96
|
+
|
|
97
|
+
return cls._views_cache
|
|
98
|
+
|
|
99
|
+
@classmethod
|
|
100
|
+
def invalidate_cache(cls):
|
|
101
|
+
"""Force la redécouverte des vues au prochain appel."""
|
|
102
|
+
cls._views_cache = None
|
|
103
|
+
cls._cache_timestamp = None
|
|
104
|
+
|
|
68
105
|
def discover_crud_views(self) -> Dict:
|
|
69
106
|
"""
|
|
70
107
|
Découvre toutes les vues CRUD du projet.
|
|
@@ -293,6 +330,9 @@ class ViewDiscoveryService:
|
|
|
293
330
|
"""
|
|
294
331
|
Récupère les informations d'une vue pour un modèle et une action.
|
|
295
332
|
|
|
333
|
+
Utilise le cache mémoire pour éviter de scanner les URLs à chaque requête.
|
|
334
|
+
Le cache est automatiquement rafraîchi après CACHE_TTL secondes.
|
|
335
|
+
|
|
296
336
|
Args:
|
|
297
337
|
model_name: Nom du modèle
|
|
298
338
|
action: Action CRUD ('list', 'create', 'detail', 'update', 'delete')
|
|
@@ -300,11 +340,8 @@ class ViewDiscoveryService:
|
|
|
300
340
|
Returns:
|
|
301
341
|
Dict avec 'url_name', 'url', 'method', 'requires_pk' ou None
|
|
302
342
|
"""
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if not config.crud_views_mapping:
|
|
307
|
-
config.refresh_crud_views_mapping()
|
|
343
|
+
# Utiliser le cache mémoire (découverte dynamique)
|
|
344
|
+
crud_views_mapping = self.get_cached_views()
|
|
308
345
|
|
|
309
346
|
model_lower = model_name.lower()
|
|
310
347
|
|
|
@@ -317,10 +354,12 @@ class ViewDiscoveryService:
|
|
|
317
354
|
]
|
|
318
355
|
|
|
319
356
|
for variant in variations:
|
|
320
|
-
model_views =
|
|
357
|
+
model_views = crud_views_mapping.get(variant, {})
|
|
321
358
|
if model_views and action in model_views:
|
|
359
|
+
LogUtils.info(f"[ViewDiscovery] Vue trouvée: {variant}.{action} -> {model_views[action].get('url_name')}")
|
|
322
360
|
return model_views.get(action)
|
|
323
361
|
|
|
362
|
+
LogUtils.info(f"[ViewDiscovery] Aucune vue trouvée pour {model_name}.{action}")
|
|
324
363
|
return None
|
|
325
364
|
|
|
326
365
|
def get_all_discovered_models(self) -> List[str]:
|
|
@@ -330,10 +369,5 @@ class ViewDiscoveryService:
|
|
|
330
369
|
Returns:
|
|
331
370
|
Liste des noms de modèles
|
|
332
371
|
"""
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
if not config.crud_views_mapping:
|
|
337
|
-
config.refresh_crud_views_mapping()
|
|
338
|
-
|
|
339
|
-
return list(config.crud_views_mapping.keys())
|
|
372
|
+
crud_views_mapping = self.get_cached_views()
|
|
373
|
+
return list(crud_views_mapping.keys())
|
|
@@ -113,9 +113,17 @@
|
|
|
113
113
|
transform: translateX(100%);
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
/* Sidebar expanded (80% width) */
|
|
117
|
+
.lucy-sidebar.expanded {
|
|
118
|
+
width: 90vw;
|
|
119
|
+
max-width: 90vw;
|
|
120
|
+
}
|
|
121
|
+
|
|
116
122
|
@media (max-width: 640px) {
|
|
117
|
-
.lucy-sidebar
|
|
123
|
+
.lucy-sidebar,
|
|
124
|
+
.lucy-sidebar.expanded {
|
|
118
125
|
width: 100%;
|
|
126
|
+
max-width: 100vw;
|
|
119
127
|
}
|
|
120
128
|
}
|
|
121
129
|
|
|
@@ -304,6 +312,7 @@
|
|
|
304
312
|
.lucy-messages {
|
|
305
313
|
flex: 1;
|
|
306
314
|
overflow-y: auto;
|
|
315
|
+
overflow-x: hidden;
|
|
307
316
|
padding: 1rem;
|
|
308
317
|
display: flex;
|
|
309
318
|
flex-direction: column;
|
|
@@ -389,6 +398,7 @@
|
|
|
389
398
|
display: flex;
|
|
390
399
|
gap: 0.5rem;
|
|
391
400
|
max-width: 85%;
|
|
401
|
+
min-width: 0;
|
|
392
402
|
}
|
|
393
403
|
|
|
394
404
|
.lucy-message.user {
|
|
@@ -422,6 +432,9 @@
|
|
|
422
432
|
.lucy-message-content {
|
|
423
433
|
display: flex;
|
|
424
434
|
flex-direction: column;
|
|
435
|
+
min-width: 0;
|
|
436
|
+
max-width: 100%;
|
|
437
|
+
overflow: hidden;
|
|
425
438
|
}
|
|
426
439
|
|
|
427
440
|
.lucy-message-bubble {
|
|
@@ -430,6 +443,9 @@
|
|
|
430
443
|
font-size: 0.875rem;
|
|
431
444
|
line-height: 1.5;
|
|
432
445
|
word-wrap: break-word;
|
|
446
|
+
overflow-wrap: break-word;
|
|
447
|
+
max-width: 100%;
|
|
448
|
+
overflow-x: auto;
|
|
433
449
|
}
|
|
434
450
|
|
|
435
451
|
.lucy-message.bot .lucy-message-bubble {
|
|
@@ -897,6 +913,9 @@
|
|
|
897
913
|
border-radius: 0.375rem;
|
|
898
914
|
overflow-x: auto;
|
|
899
915
|
margin: 0.5rem 0;
|
|
916
|
+
max-width: 100%;
|
|
917
|
+
white-space: pre-wrap;
|
|
918
|
+
word-break: break-word;
|
|
900
919
|
}
|
|
901
920
|
|
|
902
921
|
.lucy-message-bubble code {
|
|
@@ -909,6 +928,34 @@
|
|
|
909
928
|
text-decoration: underline;
|
|
910
929
|
}
|
|
911
930
|
|
|
931
|
+
/* Tables in messages */
|
|
932
|
+
.lucy-message-bubble table {
|
|
933
|
+
border-collapse: collapse;
|
|
934
|
+
font-size: 0.75rem;
|
|
935
|
+
margin: 0.5rem 0;
|
|
936
|
+
width: max-content;
|
|
937
|
+
max-width: 100%;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
.lucy-message-bubble th,
|
|
941
|
+
.lucy-message-bubble td {
|
|
942
|
+
border: 1px solid var(--lucy-border);
|
|
943
|
+
padding: 0.25rem 0.5rem;
|
|
944
|
+
text-align: left;
|
|
945
|
+
white-space: nowrap;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
.lucy-message-bubble th {
|
|
949
|
+
background: var(--lucy-bg-darker);
|
|
950
|
+
font-weight: 600;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/* Markdown content wrapper for overflow */
|
|
954
|
+
.lucy-message-bubble .markdown-content {
|
|
955
|
+
overflow-x: auto;
|
|
956
|
+
max-width: 100%;
|
|
957
|
+
}
|
|
958
|
+
|
|
912
959
|
/* ========================================
|
|
913
960
|
DOCUMENTATION - COLLAPSE/ACCORDION
|
|
914
961
|
======================================== */
|
|
@@ -9,6 +9,7 @@ function lucyAssist() {
|
|
|
9
9
|
return {
|
|
10
10
|
// État de l'interface
|
|
11
11
|
isOpen: false,
|
|
12
|
+
isExpanded: false,
|
|
12
13
|
isLoading: false,
|
|
13
14
|
showHistory: false,
|
|
14
15
|
showDoc: false,
|
|
@@ -86,6 +87,7 @@ function lucyAssist() {
|
|
|
86
87
|
saveState() {
|
|
87
88
|
const state = {
|
|
88
89
|
isOpen: this.isOpen,
|
|
90
|
+
isExpanded: this.isExpanded,
|
|
89
91
|
currentConversationId: this.currentConversationId,
|
|
90
92
|
showHistory: this.showHistory,
|
|
91
93
|
showDoc: this.showDoc
|
|
@@ -102,6 +104,7 @@ function lucyAssist() {
|
|
|
102
104
|
if (savedState) {
|
|
103
105
|
const state = JSON.parse(savedState);
|
|
104
106
|
this.isOpen = state.isOpen || false;
|
|
107
|
+
this.isExpanded = state.isExpanded || false;
|
|
105
108
|
this.currentConversationId = state.currentConversationId || null;
|
|
106
109
|
this.showHistory = state.showHistory || false;
|
|
107
110
|
this.showDoc = state.showDoc || false;
|
|
@@ -148,6 +151,14 @@ function lucyAssist() {
|
|
|
148
151
|
this.showDoc = false;
|
|
149
152
|
},
|
|
150
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Toggle du mode agrandi (80% de la fenetre)
|
|
156
|
+
*/
|
|
157
|
+
toggleExpanded() {
|
|
158
|
+
this.isExpanded = !this.isExpanded;
|
|
159
|
+
this.saveState();
|
|
160
|
+
},
|
|
161
|
+
|
|
151
162
|
/**
|
|
152
163
|
* Vérifie si c'est le premier lancement
|
|
153
164
|
*/
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
x-transition:leave-start="transform translate-x-0"
|
|
35
35
|
x-transition:leave-end="transform translate-x-full"
|
|
36
36
|
class="lucy-sidebar"
|
|
37
|
-
:class="{ 'hidden': !isOpen }"
|
|
37
|
+
:class="{ 'hidden': !isOpen, 'expanded': isExpanded }"
|
|
38
38
|
style="display: none;"
|
|
39
39
|
x-cloak
|
|
40
40
|
>
|
|
@@ -42,6 +42,16 @@
|
|
|
42
42
|
<div class="lucy-header">
|
|
43
43
|
<span class="lucy-header-title">Lucy Assist</span>
|
|
44
44
|
<div class="lucy-header-actions">
|
|
45
|
+
{# Bouton Agrandir/Reduire #}
|
|
46
|
+
<button
|
|
47
|
+
@click="toggleExpanded()"
|
|
48
|
+
class="lucy-header-btn"
|
|
49
|
+
:class="{ 'active': isExpanded }"
|
|
50
|
+
:title="isExpanded ? 'Reduire la fenetre' : 'Agrandir la fenetre'"
|
|
51
|
+
>
|
|
52
|
+
<i class="fa-solid" :class="isExpanded ? 'fa-compress' : 'fa-expand'"></i>
|
|
53
|
+
</button>
|
|
54
|
+
|
|
45
55
|
{# Bouton Historique #}
|
|
46
56
|
<button
|
|
47
57
|
@click="showHistory = !showHistory; showDoc = false"
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
lucy_assist/__init__.py,sha256=9NTQKOljcruDMZjj1WQhcSRRjLbrx61jyaTuhXpk9ds,325
|
|
2
|
-
lucy_assist/admin.py,sha256=CFVBPmuFRIJzxc2pZ9s3LK1kdxMhSbLVA022VgbH89Y,4734
|
|
3
|
-
lucy_assist/apps.py,sha256=zHZtlBXs5ML4CKtGg7xDyptSWzLfB1ks2VvbXF50hdo,264
|
|
4
|
-
lucy_assist/conf.py,sha256=RgtZSrUwHZjjbEGZqQvifvC4GNdICmhty2XetfvAbls,3992
|
|
5
|
-
lucy_assist/constantes.py,sha256=9L2VGBK0HorJoNDGdwQlhEfT75W-xNPAhtS0-qgawBs,3947
|
|
6
|
-
lucy_assist/context_processors.py,sha256=tnzil4CEJwtExuQGLyRzIEuwpQfnwJ-eMgkkR6zNgSg,2200
|
|
7
|
-
lucy_assist/signals.py,sha256=i3Uj9v-0zyAIROFl86fLlwaqRqQizL9_CpWmVjJbk8g,863
|
|
8
|
-
lucy_assist/urls.py,sha256=Qr8jJjEyC_EFGAeiZnjhgTc-9P4Y-TqKDaYicWRp_GQ,1451
|
|
9
|
-
lucy_assist/migrations/0001_initial.py,sha256=quQUw6is5clu3Q4B3P_0mUZVE33lSvdimH_OTCY3ycE,4977
|
|
10
|
-
lucy_assist/migrations/0002_configurationlucyassist_prompt_complementaire.py,sha256=yWE4-RPHQtPAqYHlAhr4EsXgk35kI8zRQArlAP_JwDc,418
|
|
11
|
-
lucy_assist/migrations/0003_configurationlucyassist_crud_views_mapping.py,sha256=1vnu1VwVBouskhQBgLz-Lp71p4a9Cb9PjrT-RLVGY7s,429
|
|
12
|
-
lucy_assist/migrations/0004_configurationlucyassist_system_prompt.py,sha256=0a78xO15oiLcCSlO8BicMac_QE8IfiNSt9WlGptVNNo,568
|
|
13
|
-
lucy_assist/migrations/0005_configurationlucyassist_project_context.py,sha256=6eZCssiWylS_9pg9wDExbUZWEDwk2zaVu_f3pqMzuz8,564
|
|
14
|
-
lucy_assist/migrations/0006_remove_configurationlucyassist_prompt_complementaire.py,sha256=AwTzbmZWfWJ7Q_kcbSspSOiVJgHzGLLeMupeRSSVuI4,359
|
|
15
|
-
lucy_assist/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
lucy_assist/models/__init__.py,sha256=JQMr50P94sBrKwwcNArRE_qnk7dLnknMKCabeRLskJc,415
|
|
17
|
-
lucy_assist/models/base.py,sha256=Ql2AY7bzvcxZhxsPdCpbVEKvtWD-NBkHTLYZX4TjT3s,1532
|
|
18
|
-
lucy_assist/models/configuration.py,sha256=GHmgkVZk3m01vlDwT-YEn4UG4za8e3Qr7xK00vsd_Qc,17095
|
|
19
|
-
lucy_assist/models/conversation.py,sha256=psx2AQtQ5SFP-AJD7wbGabpXXLIGYngdVZfeoTlgKtQ,1849
|
|
20
|
-
lucy_assist/models/message.py,sha256=kf-ffMtLYNFhXYUrB3QSL97KKDJUOMrKaPjKeOcJa_o,1492
|
|
21
|
-
lucy_assist/models/project_context_cache.py,sha256=Bnb0VU7pv7QEvjOI6JSLEPvL4BxskCQ0ojWGxO7YDSM,6530
|
|
22
|
-
lucy_assist/services/__init__.py,sha256=2Txqcn_M33amvlI1KZLJk9RXvu0s0I2-GfYKX_RAe3w,807
|
|
23
|
-
lucy_assist/services/bug_notification_service.py,sha256=OyowCvAs-QDlsGQ_WTFoc4lRe9detD7r6ZyYK0JD2Sc,7217
|
|
24
|
-
lucy_assist/services/context_service.py,sha256=Vx2tR6W1jmqr06pGn924uzWTF2SV7RAO_JIScxYbCy0,17087
|
|
25
|
-
lucy_assist/services/crud_service.py,sha256=W50K02ZkaScyzO-yRaBd9Cjva9PGH7OjNTipSruErcA,41495
|
|
26
|
-
lucy_assist/services/gitlab_service.py,sha256=uH83fwRSCwiRItznENpYQG4aPckjafYIV9z6OChUrZg,8056
|
|
27
|
-
lucy_assist/services/mistral_service.py,sha256=mmoI2ixBFTeKFOId-2goe-NGpvjd_cMW9PMuV2C-P2k,18624
|
|
28
|
-
lucy_assist/services/project_context_service.py,sha256=6QNVL-K2D-8whIPfyAJhi_xAifqTXxR09461YNBwg4o,14826
|
|
29
|
-
lucy_assist/services/tool_executor_service.py,sha256=nTeJbj2JUDMk_bmLVgGxtWqFbSgywq-tNRBK-_3Yayw,15155
|
|
30
|
-
lucy_assist/services/tools_definition.py,sha256=qIiIoB5_QMqmkD03OOEk_3A5Nc0g0avAjDCj3Uq3_r8,11735
|
|
31
|
-
lucy_assist/services/view_discovery_service.py,sha256=J9LkHXUOzlGS3cyft2_jA1X27TWOd3xViN4M7GOROVw,11872
|
|
32
|
-
lucy_assist/static/lucy_assist/css/lucy-assist.css,sha256=7bJfV31cIgOFJQ8RQ0vIqgel6dM8dh5W2wshv6MHjxs,23325
|
|
33
|
-
lucy_assist/static/lucy_assist/image/icon-lucy.png,sha256=FOYlwXAt40Gr9jsWFmhgPivYOBFWKeYW0lxJI5Up-GM,6710
|
|
34
|
-
lucy_assist/static/lucy_assist/js/lucy-assist.js,sha256=dmXtSPQ38LisoRWZd3R1Ms6OvVaEk3OrYKcVM0OMb_Q,28207
|
|
35
|
-
lucy_assist/templates/lucy_assist/chatbot_sidebar.html,sha256=HtxR8G0c21vWmaXN4ALJXT7VhdUlOhtheeu8kk7Emjg,18925
|
|
36
|
-
lucy_assist/templates/lucy_assist/partials/documentation_content.html,sha256=twbe3TvuPfy1Et2LMElK0JJNq2awb3SnIouA8v8NeWs,4143
|
|
37
|
-
lucy_assist/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
-
lucy_assist/tests/test_lucy_assist.py,sha256=KBvuED10_gOJWdaRS2zMigM3W5Kp00KhMEwaR8tvhUc,6949
|
|
39
|
-
lucy_assist/tests/factories/__init__.py,sha256=cDkgr4aPFKwbPo6JLY2s22pHrGWPI_vqG4IafWAhSmE,376
|
|
40
|
-
lucy_assist/tests/factories/lucy_assist_factories.py,sha256=Mz1EN7xtMpIDJPNMledDbjR6X6dsBNv7JWczjD9-_MQ,3674
|
|
41
|
-
lucy_assist/utils/__init__.py,sha256=FnL0QF7pyhjHCOywVAkZq3dl4IEgT39prJk1FtXMBDc,129
|
|
42
|
-
lucy_assist/utils/log_utils.py,sha256=gdjaKg5PNUYlDVCQNFXQJG3vsLKay_aWX6AJxoHtiG4,1720
|
|
43
|
-
lucy_assist/utils/message_utils.py,sha256=YzcLHnl1ig4d5_utHCJwgxS7tKmd49Q-tuo78e6w2Ww,4494
|
|
44
|
-
lucy_assist/utils/token_utils.py,sha256=aBzyKVqpU67rAetO_Ee3QIfPtbNyjyWSe6qPfzIRJF8,2608
|
|
45
|
-
lucy_assist/views/__init__.py,sha256=uUPYpuHlBC8j7zKS_DDoWjwpCpRnOIXETY-S2-Ss0cY,288
|
|
46
|
-
lucy_assist/views/api_views.py,sha256=sJwKNC9-mi1zMbgyKZTVvT3pz4hMmw4jR0rrS7iJR-g,23619
|
|
47
|
-
django_lucy_assist-1.2.3.dist-info/METADATA,sha256=JDd1H3wg2RpwLmeVdA-Ednz73-6-St1r3oSHWu3ztdQ,5899
|
|
48
|
-
django_lucy_assist-1.2.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
49
|
-
django_lucy_assist-1.2.3.dist-info/top_level.txt,sha256=T-UCiwpn5yF3Oem3234TUpSVnEgbkrM2rGz9Tz5N-QA,12
|
|
50
|
-
django_lucy_assist-1.2.3.dist-info/RECORD,,
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# Generated by Django 6.0.1 on 2026-01-27 09:51
|
|
2
|
-
|
|
3
|
-
from django.db import migrations, models
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class Migration(migrations.Migration):
|
|
7
|
-
|
|
8
|
-
dependencies = [
|
|
9
|
-
('lucy_assist', '0001_initial'),
|
|
10
|
-
]
|
|
11
|
-
|
|
12
|
-
operations = [
|
|
13
|
-
migrations.AddField(
|
|
14
|
-
model_name='configurationlucyassist',
|
|
15
|
-
name='prompt_complementaire',
|
|
16
|
-
field=models.TextField(blank=True, default=''),
|
|
17
|
-
),
|
|
18
|
-
]
|
|
@@ -1,18 +0,0 @@
|
|
|
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', '0002_configurationlucyassist_prompt_complementaire'),
|
|
10
|
-
]
|
|
11
|
-
|
|
12
|
-
operations = [
|
|
13
|
-
migrations.AddField(
|
|
14
|
-
model_name='configurationlucyassist',
|
|
15
|
-
name='crud_views_mapping',
|
|
16
|
-
field=models.JSONField(blank=True, default=dict),
|
|
17
|
-
),
|
|
18
|
-
]
|
|
@@ -1,22 +0,0 @@
|
|
|
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
|
-
]
|
|
@@ -1,22 +0,0 @@
|
|
|
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', '0004_configurationlucyassist_system_prompt'),
|
|
10
|
-
]
|
|
11
|
-
|
|
12
|
-
operations = [
|
|
13
|
-
migrations.AddField(
|
|
14
|
-
model_name='configurationlucyassist',
|
|
15
|
-
name='project_context',
|
|
16
|
-
field=models.TextField(
|
|
17
|
-
blank=True,
|
|
18
|
-
default='',
|
|
19
|
-
help_text="Contexte du projet analyse depuis GitLab. Rafraichir via l'action admin."
|
|
20
|
-
),
|
|
21
|
-
),
|
|
22
|
-
]
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# Generated by Django
|
|
2
|
-
|
|
3
|
-
from django.db import migrations
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class Migration(migrations.Migration):
|
|
7
|
-
|
|
8
|
-
dependencies = [
|
|
9
|
-
('lucy_assist', '0005_configurationlucyassist_project_context'),
|
|
10
|
-
]
|
|
11
|
-
|
|
12
|
-
operations = [
|
|
13
|
-
migrations.RemoveField(
|
|
14
|
-
model_name='configurationlucyassist',
|
|
15
|
-
name='prompt_complementaire',
|
|
16
|
-
),
|
|
17
|
-
]
|
|
File without changes
|
|
File without changes
|