ux: bouton 'Soumettre' post-hoc sous Lancer (Enrich/Audit/Signalement)
Browse filesApres une analyse, sous le bouton 'Lancer …' (primary violet) apparait
un bouton 'Soumettre a JDM (post-hoc)' en variant=stop (rouge), visible
des qu'un fichier .enrich/.audit/.err a ete produit (je_file.change()).
Logique de grise :
- Au build : interactive selon que JDM_DROPS_API_KEY est dans l'env.
- Quand jarvis_drops_key change (bandeau), un wire transverse rafraichit
les 3 boutons (cle UI override env -> bouton actif).
- Quand un fichier est produit : visible=True + interactive recalcule.
Au clic, appelle submit_to_jdm via le nouvel helper
jarvis.submit_existing_file() qui :
- override temporairement JDM_DROPS_API_KEY avec drops_key UI si fournie
- appelle submit_to_jdm(path, model_name=…)
- append le verdict (OK/echec) au chatbot existant
Permet de soumettre meme si on n'avait pas coche la case 'Soumettre
directement' au lancement. 163 verts.
|
@@ -1617,6 +1617,17 @@ with gr.Blocks(theme=THEME, title="JDMAgent Demo", head=_HEAD_JS, css=_CHATBOT_C
|
|
| 1617 |
"🌱 Lancer l'enrichissement",
|
| 1618 |
variant="primary",
|
| 1619 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1620 |
with gr.Column(scale=2):
|
| 1621 |
je_chat = gr.Chatbot(
|
| 1622 |
type="messages",
|
|
@@ -1683,6 +1694,30 @@ with gr.Blocks(theme=THEME, title="JDMAgent Demo", head=_HEAD_JS, css=_CHATBOT_C
|
|
| 1683 |
outputs=[je_chat, je_file, je_preview],
|
| 1684 |
)
|
| 1685 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1686 |
with gr.Tab("🔍 Audit", id="jarvis-audit"):
|
| 1687 |
gr.Markdown(
|
| 1688 |
"Audit sémantique : détecte les CONTAMINATIONS du "
|
|
@@ -1713,6 +1748,13 @@ with gr.Blocks(theme=THEME, title="JDMAgent Demo", head=_HEAD_JS, css=_CHATBOT_C
|
|
| 1713 |
"🔍 Lancer l'audit",
|
| 1714 |
variant="primary",
|
| 1715 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1716 |
with gr.Column(scale=2):
|
| 1717 |
ja_chat = gr.Chatbot(
|
| 1718 |
type="messages",
|
|
@@ -1769,6 +1811,28 @@ with gr.Blocks(theme=THEME, title="JDMAgent Demo", head=_HEAD_JS, css=_CHATBOT_C
|
|
| 1769 |
outputs=[ja_chat, ja_file, ja_preview],
|
| 1770 |
)
|
| 1771 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1772 |
with gr.Tab("🕳️ Détection de trous", id="jarvis-gaps"):
|
| 1773 |
gr.Markdown(
|
| 1774 |
"Identifie les trous de couverture (MISSING / "
|
|
@@ -1985,6 +2049,13 @@ with gr.Blocks(theme=THEME, title="JDMAgent Demo", head=_HEAD_JS, css=_CHATBOT_C
|
|
| 1985 |
"⚠️ Scanner et signaler",
|
| 1986 |
variant="primary",
|
| 1987 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1988 |
with gr.Column(scale=2):
|
| 1989 |
js_chat = gr.Chatbot(
|
| 1990 |
type="messages",
|
|
@@ -2041,6 +2112,28 @@ with gr.Blocks(theme=THEME, title="JDMAgent Demo", head=_HEAD_JS, css=_CHATBOT_C
|
|
| 2041 |
outputs=[js_chat, js_file, js_preview],
|
| 2042 |
)
|
| 2043 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2044 |
with gr.Tab("📊 Stats", id="jarvis-stats"):
|
| 2045 |
gr.Markdown(
|
| 2046 |
"Statistiques de couverture JDM. Deux modes "
|
|
@@ -2145,6 +2238,28 @@ with gr.Blocks(theme=THEME, title="JDMAgent Demo", head=_HEAD_JS, css=_CHATBOT_C
|
|
| 2145 |
outputs=[jst_term, jst_relation, jarvis_tabs],
|
| 2146 |
)
|
| 2147 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2148 |
# ----- Tab 6: Aide / Installation (Phase 13.7) -----
|
| 2149 |
with gr.Tab("🛠️ Aide / Installation"):
|
| 2150 |
gr.Markdown(AIDE_MD)
|
|
|
|
| 1617 |
"🌱 Lancer l'enrichissement",
|
| 1618 |
variant="primary",
|
| 1619 |
)
|
| 1620 |
+
# Bouton de soumission post-hoc — apparaît une
|
| 1621 |
+
# fois qu'un fichier .enrich a été produit.
|
| 1622 |
+
# Variant 'stop' (rouge) pour le distinguer du
|
| 1623 |
+
# primary 'Lancer'. Grisé si pas de clé Drops.
|
| 1624 |
+
from jarvis import has_drops_key as _has_dk
|
| 1625 |
+
je_submit = gr.Button(
|
| 1626 |
+
"📤 Soumettre à JDM (post-hoc)",
|
| 1627 |
+
variant="stop",
|
| 1628 |
+
visible=False,
|
| 1629 |
+
interactive=_has_dk(),
|
| 1630 |
+
)
|
| 1631 |
with gr.Column(scale=2):
|
| 1632 |
je_chat = gr.Chatbot(
|
| 1633 |
type="messages",
|
|
|
|
| 1694 |
outputs=[je_chat, je_file, je_preview],
|
| 1695 |
)
|
| 1696 |
|
| 1697 |
+
# Quand un fichier est produit (je_file devient visible),
|
| 1698 |
+
# on rend visible le bouton « Soumettre » post-hoc.
|
| 1699 |
+
def _show_submit_btn(file_path, drops_key):
|
| 1700 |
+
if not file_path:
|
| 1701 |
+
return gr.update(visible=False)
|
| 1702 |
+
from jarvis import has_drops_key as _hk
|
| 1703 |
+
return gr.update(visible=True, interactive=_hk(drops_key))
|
| 1704 |
+
|
| 1705 |
+
je_file.change(
|
| 1706 |
+
_show_submit_btn,
|
| 1707 |
+
inputs=[je_file, jarvis_drops_key],
|
| 1708 |
+
outputs=[je_submit],
|
| 1709 |
+
)
|
| 1710 |
+
|
| 1711 |
+
def _submit_enrich(file_path, drops_key, model, chat):
|
| 1712 |
+
from jarvis import submit_existing_file
|
| 1713 |
+
return submit_existing_file(file_path, drops_key, model, chat)
|
| 1714 |
+
|
| 1715 |
+
je_submit.click(
|
| 1716 |
+
_submit_enrich,
|
| 1717 |
+
inputs=[je_file, jarvis_drops_key, jarvis_model, je_chat],
|
| 1718 |
+
outputs=[je_chat],
|
| 1719 |
+
)
|
| 1720 |
+
|
| 1721 |
with gr.Tab("🔍 Audit", id="jarvis-audit"):
|
| 1722 |
gr.Markdown(
|
| 1723 |
"Audit sémantique : détecte les CONTAMINATIONS du "
|
|
|
|
| 1748 |
"🔍 Lancer l'audit",
|
| 1749 |
variant="primary",
|
| 1750 |
)
|
| 1751 |
+
from jarvis import has_drops_key as _hk_a
|
| 1752 |
+
ja_submit = gr.Button(
|
| 1753 |
+
"📤 Soumettre à JDM (post-hoc)",
|
| 1754 |
+
variant="stop",
|
| 1755 |
+
visible=False,
|
| 1756 |
+
interactive=_hk_a(),
|
| 1757 |
+
)
|
| 1758 |
with gr.Column(scale=2):
|
| 1759 |
ja_chat = gr.Chatbot(
|
| 1760 |
type="messages",
|
|
|
|
| 1811 |
outputs=[ja_chat, ja_file, ja_preview],
|
| 1812 |
)
|
| 1813 |
|
| 1814 |
+
def _show_audit_submit(file_path, drops_key):
|
| 1815 |
+
if not file_path:
|
| 1816 |
+
return gr.update(visible=False)
|
| 1817 |
+
from jarvis import has_drops_key as _hk
|
| 1818 |
+
return gr.update(visible=True, interactive=_hk(drops_key))
|
| 1819 |
+
|
| 1820 |
+
ja_file.change(
|
| 1821 |
+
_show_audit_submit,
|
| 1822 |
+
inputs=[ja_file, jarvis_drops_key],
|
| 1823 |
+
outputs=[ja_submit],
|
| 1824 |
+
)
|
| 1825 |
+
|
| 1826 |
+
def _submit_audit(file_path, drops_key, model, chat):
|
| 1827 |
+
from jarvis import submit_existing_file
|
| 1828 |
+
return submit_existing_file(file_path, drops_key, model, chat)
|
| 1829 |
+
|
| 1830 |
+
ja_submit.click(
|
| 1831 |
+
_submit_audit,
|
| 1832 |
+
inputs=[ja_file, jarvis_drops_key, jarvis_model, ja_chat],
|
| 1833 |
+
outputs=[ja_chat],
|
| 1834 |
+
)
|
| 1835 |
+
|
| 1836 |
with gr.Tab("🕳️ Détection de trous", id="jarvis-gaps"):
|
| 1837 |
gr.Markdown(
|
| 1838 |
"Identifie les trous de couverture (MISSING / "
|
|
|
|
| 2049 |
"⚠️ Scanner et signaler",
|
| 2050 |
variant="primary",
|
| 2051 |
)
|
| 2052 |
+
from jarvis import has_drops_key as _hk_s
|
| 2053 |
+
js_submit = gr.Button(
|
| 2054 |
+
"📤 Soumettre à JDM (post-hoc)",
|
| 2055 |
+
variant="stop",
|
| 2056 |
+
visible=False,
|
| 2057 |
+
interactive=_hk_s(),
|
| 2058 |
+
)
|
| 2059 |
with gr.Column(scale=2):
|
| 2060 |
js_chat = gr.Chatbot(
|
| 2061 |
type="messages",
|
|
|
|
| 2112 |
outputs=[js_chat, js_file, js_preview],
|
| 2113 |
)
|
| 2114 |
|
| 2115 |
+
def _show_signal_submit(file_path, drops_key):
|
| 2116 |
+
if not file_path:
|
| 2117 |
+
return gr.update(visible=False)
|
| 2118 |
+
from jarvis import has_drops_key as _hk
|
| 2119 |
+
return gr.update(visible=True, interactive=_hk(drops_key))
|
| 2120 |
+
|
| 2121 |
+
js_file.change(
|
| 2122 |
+
_show_signal_submit,
|
| 2123 |
+
inputs=[js_file, jarvis_drops_key],
|
| 2124 |
+
outputs=[js_submit],
|
| 2125 |
+
)
|
| 2126 |
+
|
| 2127 |
+
def _submit_signal(file_path, drops_key, model, chat):
|
| 2128 |
+
from jarvis import submit_existing_file
|
| 2129 |
+
return submit_existing_file(file_path, drops_key, model, chat)
|
| 2130 |
+
|
| 2131 |
+
js_submit.click(
|
| 2132 |
+
_submit_signal,
|
| 2133 |
+
inputs=[js_file, jarvis_drops_key, jarvis_model, js_chat],
|
| 2134 |
+
outputs=[js_chat],
|
| 2135 |
+
)
|
| 2136 |
+
|
| 2137 |
with gr.Tab("📊 Stats", id="jarvis-stats"):
|
| 2138 |
gr.Markdown(
|
| 2139 |
"Statistiques de couverture JDM. Deux modes "
|
|
|
|
| 2238 |
outputs=[jst_term, jst_relation, jarvis_tabs],
|
| 2239 |
)
|
| 2240 |
|
| 2241 |
+
# ---- Câblage transverse : quand la clé LLMDrops change dans
|
| 2242 |
+
# le bandeau, on rafraîchit l'état interactive des 3 boutons
|
| 2243 |
+
# « Soumettre » post-hoc (s'ils sont déjà visibles). Si le
|
| 2244 |
+
# bouton n'est pas encore visible (pas de fichier produit),
|
| 2245 |
+
# on garde son visible=False.
|
| 2246 |
+
def _refresh_submit_buttons(drops_key):
|
| 2247 |
+
from jarvis import has_drops_key as _hk
|
| 2248 |
+
ok = _hk(drops_key)
|
| 2249 |
+
# Le `interactive` se met à jour même quand visible=False ;
|
| 2250 |
+
# quand le bouton deviendra visible, l'état est cohérent.
|
| 2251 |
+
return (
|
| 2252 |
+
gr.update(interactive=ok),
|
| 2253 |
+
gr.update(interactive=ok),
|
| 2254 |
+
gr.update(interactive=ok),
|
| 2255 |
+
)
|
| 2256 |
+
|
| 2257 |
+
jarvis_drops_key.change(
|
| 2258 |
+
_refresh_submit_buttons,
|
| 2259 |
+
inputs=[jarvis_drops_key],
|
| 2260 |
+
outputs=[je_submit, ja_submit, js_submit],
|
| 2261 |
+
)
|
| 2262 |
+
|
| 2263 |
# ----- Tab 6: Aide / Installation (Phase 13.7) -----
|
| 2264 |
with gr.Tab("🛠️ Aide / Installation"):
|
| 2265 |
gr.Markdown(AIDE_MD)
|
|
@@ -413,6 +413,70 @@ def _read_file_preview(path: Optional[str], max_chars: int = 6000) -> str:
|
|
| 413 |
return text
|
| 414 |
|
| 415 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 416 |
def run_jarvis_flow(
|
| 417 |
prompt: str,
|
| 418 |
*,
|
|
|
|
| 413 |
return text
|
| 414 |
|
| 415 |
|
| 416 |
+
def submit_existing_file(
|
| 417 |
+
file_path: Optional[str],
|
| 418 |
+
drops_key: str,
|
| 419 |
+
model_name: str,
|
| 420 |
+
current_chat: Optional[list[dict]] = None,
|
| 421 |
+
) -> list[dict]:
|
| 422 |
+
"""Soumet un fichier .enrich/.audit/.err déjà produit au LLMDrops JDM.
|
| 423 |
+
|
| 424 |
+
À utiliser pour le bouton « 📤 Soumettre » post-hoc des sous-onglets
|
| 425 |
+
Jarvis. Si une clé est fournie côté UI (`drops_key`), elle override
|
| 426 |
+
temporairement `JDM_DROPS_API_KEY` le temps de l'appel.
|
| 427 |
+
|
| 428 |
+
Renvoie la liste de messages mise à jour pour le `gr.Chatbot` (append
|
| 429 |
+
d'un message assistant avec le verdict).
|
| 430 |
+
"""
|
| 431 |
+
import os
|
| 432 |
+
from jdm_agent.enrich.uploader import submit_to_jdm
|
| 433 |
+
|
| 434 |
+
chat = list(current_chat) if current_chat else []
|
| 435 |
+
|
| 436 |
+
if not file_path:
|
| 437 |
+
chat.append({
|
| 438 |
+
"role": "assistant",
|
| 439 |
+
"content": "⚠️ Aucun fichier produit à soumettre."
|
| 440 |
+
})
|
| 441 |
+
return chat
|
| 442 |
+
|
| 443 |
+
saved = os.environ.get("JDM_DROPS_API_KEY")
|
| 444 |
+
if drops_key and drops_key.strip():
|
| 445 |
+
os.environ["JDM_DROPS_API_KEY"] = drops_key.strip()
|
| 446 |
+
try:
|
| 447 |
+
result = submit_to_jdm(file_path, model_name=(model_name or "").strip() or None)
|
| 448 |
+
finally:
|
| 449 |
+
if drops_key and drops_key.strip():
|
| 450 |
+
if saved is None:
|
| 451 |
+
os.environ.pop("JDM_DROPS_API_KEY", None)
|
| 452 |
+
else:
|
| 453 |
+
os.environ["JDM_DROPS_API_KEY"] = saved
|
| 454 |
+
|
| 455 |
+
if result.get("ok"):
|
| 456 |
+
chat.append({
|
| 457 |
+
"role": "assistant",
|
| 458 |
+
"content": (
|
| 459 |
+
f"✅ Fichier soumis à JDM (status {result.get('status_code')}) — "
|
| 460 |
+
f"uploadé sous le nom `{result.get('uploaded_as')}`.\n\n"
|
| 461 |
+
f"Réponse serveur : `{result.get('response')}`"
|
| 462 |
+
)
|
| 463 |
+
})
|
| 464 |
+
else:
|
| 465 |
+
chat.append({
|
| 466 |
+
"role": "assistant",
|
| 467 |
+
"content": f"❌ Échec de soumission : {result.get('error', 'inconnu')}"
|
| 468 |
+
})
|
| 469 |
+
return chat
|
| 470 |
+
|
| 471 |
+
|
| 472 |
+
def has_drops_key(ui_key: str = "") -> bool:
|
| 473 |
+
"""True si une clé LLMDrops est disponible (UI override OU env)."""
|
| 474 |
+
import os
|
| 475 |
+
if ui_key and ui_key.strip():
|
| 476 |
+
return True
|
| 477 |
+
return bool(os.environ.get("JDM_DROPS_API_KEY", "").strip())
|
| 478 |
+
|
| 479 |
+
|
| 480 |
def run_jarvis_flow(
|
| 481 |
prompt: str,
|
| 482 |
*,
|