feat(agent): mock hors-ligne genere du contenu utile (Ask AI page + AI meeting note)
This commit is contained in:
@@ -11,6 +11,10 @@
|
||||
n'existait (`send()` retournait silencieusement sans `currentConv`). Ajout d'une création de
|
||||
conversation **lazy** (`ensureConversation()`) effectuée avant chaque envoi — la 1ère saisie crée
|
||||
la conversation puis l'exécute (mode offline ou LLM réel).
|
||||
- **Mode hors-ligne plus utile** : le mock LLM (`_draft_reply`) génère désormais un **vrai contenu
|
||||
structuré** pour les demandes de rédaction de page (« Ask AI », titre détecté via « intitulée »)
|
||||
et les **AI meeting notes** (squelette Résumé / Décisions / Action items), au lieu de se contenter
|
||||
de renvoyer le prompt tel quel — les boutons produisent donc du contenu même sans clé API.
|
||||
- **« Ask AI » & « AI meeting note »** : ne faisaient qu'insérer du texte placeholder
|
||||
(« Ask AI to write... » / « AI Meeting Note ») sans aucun appel IA. Ils déclenchent désormais une
|
||||
**génération inline réelle** via le FlowDeck Agent :
|
||||
|
||||
@@ -247,6 +247,10 @@ class LLMClient:
|
||||
)
|
||||
|
||||
# Plain conversational objective → final answer (no tool).
|
||||
draft = self._draft_reply(user_content)
|
||||
if draft:
|
||||
return LLMResponse(text=draft, model=model)
|
||||
|
||||
return LLMResponse(
|
||||
text=self._summarize(user_content),
|
||||
model=model,
|
||||
@@ -288,4 +292,80 @@ class LLMClient:
|
||||
def _summarize(content: str) -> str:
|
||||
"""Produce a terse final summary from a conversational objective."""
|
||||
content = content.split("\n# Contexte")[0]
|
||||
return (content[:600] + "…" if len(content) > 600 else content)
|
||||
return (content[:600] + "…" if len(content) > 600 else content)
|
||||
|
||||
def _draft_reply(self, content: str) -> str | None:
|
||||
"""Generate usable structured copy for content/meeting requests when no
|
||||
real LLM is configured (offline mock). Returns None when the message is
|
||||
not a clear content-generation intent so other paths keep their behavior.
|
||||
"""
|
||||
from datetime import date
|
||||
|
||||
low = content.lower()
|
||||
title = None
|
||||
m = re.search(r"intitul[ée]e\s*[«\"']([^»\"']+)[»\"']", content)
|
||||
if m:
|
||||
title = m.group(1).strip()
|
||||
today = date.today().isoformat()
|
||||
|
||||
# ── AI meeting note template ──
|
||||
if any(k in low for k in ("ai meeting note", "meeting note",
|
||||
"compte-rendu", "compte rendu",
|
||||
"notes de réunion", "réunion")):
|
||||
return (
|
||||
"📅 AI Meeting Note\n"
|
||||
f"Date : {today} · Participants : (à renseigner)\n"
|
||||
"\n"
|
||||
"## Résumé\n"
|
||||
"Point central de la discussion et contexte (à compléter).\n"
|
||||
"\n"
|
||||
"## Décisions\n"
|
||||
"• Décision 1 — valider le périmètre et les responsables.\n"
|
||||
"• Décision 2 — définir la prochaine échéance.\n"
|
||||
"\n"
|
||||
"## Action items\n"
|
||||
"☐ Action 1 — responsable : …, échéance : …\n"
|
||||
"☐ Action 2 — responsable : …, échéance : …\n"
|
||||
"\n"
|
||||
"## Prochaines étapes\n"
|
||||
"• Planifier le suivi et archiver ce compte-rendu.\n"
|
||||
)
|
||||
|
||||
# ── Page / document draft (contextual "Ask AI") ──
|
||||
if title:
|
||||
t = title[:80]
|
||||
return (
|
||||
f"{t}\n"
|
||||
"\n"
|
||||
f"Présentation générale du sujet « {t} » : objectif, contexte et "
|
||||
"public visé en quelques phrases. (Document généré hors-ligne — "
|
||||
"connectez une clé API pour une rédaction complète.)\n"
|
||||
"\n"
|
||||
"## Objectif\n"
|
||||
"• Clarifier le besoin couvert par ce document.\n"
|
||||
"• Lister les livrables attendus.\n"
|
||||
"\n"
|
||||
"## Points clés\n"
|
||||
"• Idée principale 1 avec les arguments associés.\n"
|
||||
"• Idée principale 2 et les exemples concrets.\n"
|
||||
"\n"
|
||||
"## Prochaines étapes\n"
|
||||
"• Relire, compléter et mettre en forme ce contenu.\n"
|
||||
)
|
||||
|
||||
# ── Generic drafting verb, no title (typing directly in the chat) ──
|
||||
if re.search(r"^(r[ée]dige|[ée]cris|g[ée]n[èe]re|produis|d[ée]veloppe|"
|
||||
r"[ée]cris\s+un|g[ée]n[èe]re\s+un|r[ée]dige\s+un)\b", low):
|
||||
return (
|
||||
"## Introduction\n"
|
||||
"Contexte et objectif de ce texte, en une à deux phrases.\n"
|
||||
"\n"
|
||||
"## Développement\n"
|
||||
"• Premier argument structuré avec un exemple.\n"
|
||||
"• Deuxième argument appuyé par une donnée ou un fait.\n"
|
||||
"\n"
|
||||
"## Conclusion\n"
|
||||
"Synthèse et prochaine étape recommandée.\n"
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user