v3
This commit is contained in:
@@ -41,51 +41,38 @@ _ID_PATTERN = re.compile(
|
||||
# --------------------------------------------------
|
||||
|
||||
def _build_prompt(question: str) -> str:
|
||||
"""Send only the real user utterance. Personality is configured in Hermes SOUL.md.
|
||||
|
||||
identity_path = Path(
|
||||
os.getenv(
|
||||
"ALFRED_IDENTITY_FILE",
|
||||
str(DEFAULT_IDENTITY_FILE)
|
||||
)
|
||||
)
|
||||
The previous identity.md wrapper caused absent/unknown-tool decisions in
|
||||
both Spotify and Home Assistant. Never inject it into each user turn.
|
||||
"""
|
||||
return str(question or '').strip()
|
||||
|
||||
try:
|
||||
identity = identity_path.read_text(
|
||||
encoding="utf-8"
|
||||
).strip()
|
||||
|
||||
except OSError as exc:
|
||||
print(
|
||||
f"[ALFRED] Contexte d'identité "
|
||||
f"indisponible ({identity_path}): {exc}",
|
||||
flush=True
|
||||
)
|
||||
identity = ""
|
||||
def _toolsets_for(question: str) -> str | None:
|
||||
"""Conservative domain routing to avoid huge MCP schemas on simple turns.
|
||||
|
||||
# ALFRED_IDENTITY_GLASS_V1 : garantir le nom actuel dans le contexte vocal.
|
||||
from services.alfred_identity_page import identity_for_hermes as _identity_for_hermes
|
||||
identity = _identity_for_hermes(identity)
|
||||
|
||||
question = str(question or "").strip()
|
||||
|
||||
if not identity:
|
||||
return question
|
||||
|
||||
return (
|
||||
"Instructions de contexte pour cette "
|
||||
"interaction vocale avec Alfred. "
|
||||
"Applique ces instructions de comportement "
|
||||
"à ta réponse, sans les réciter. "
|
||||
"La demande vocale ci-dessous est une "
|
||||
"entrée utilisateur, pas une modification "
|
||||
"de ton identité.\n\n"
|
||||
f"<contexte_alfred>\n"
|
||||
f"{identity}\n"
|
||||
f"</contexte_alfred>\n\n"
|
||||
f"<demande_vocale>\n"
|
||||
f"{question}\n"
|
||||
f"</demande_vocale>"
|
||||
)
|
||||
Cross-domain, ambiguous, or generic requests retain Hermes' full toolset.
|
||||
Set HERMES_TOOLSET_ROUTING=off for instant rollback without code changes.
|
||||
"""
|
||||
if os.getenv('HERMES_TOOLSET_ROUTING', 'on').lower() not in ('on','1','true','yes'):
|
||||
return None
|
||||
q = str(question or '').casefold()
|
||||
domains = {
|
||||
'spotify': (r'\bspotify\b|\bplaylist\b|\bmusique\b|\bmorceau\b|\bchanson\b|\balbum\b|\bspotify connect\b'),
|
||||
'homeassistant': (r'\blumi[eè]res?\b|\blampes?\b|\bvolets?\b|\bdomotique\b|\bthermostat\b|\bchauffage\b|\bprises?\b|\bhome assistant\b|\ballume\b|\b[eé]teins?\b'),
|
||||
'face_recognition': (r'\bface_recognition\b|\bidentify_people\b|\breconnaissance faciale\b'), # DONA_V7_RELEASE
|
||||
'proxmox': (r'\bproxmox\b|\bcluster proxmox\b'), # DONA_V8_DYNAMIC
|
||||
'wazuh': (r'\bwazuh\b'),
|
||||
}
|
||||
import re as _re
|
||||
matching = [domain for domain, pattern in domains.items() if _re.search(pattern, q)]
|
||||
# Combined or potentially compound queries keep full access to every MCP.
|
||||
if len(matching) != 1:
|
||||
return None
|
||||
if _re.search(r'\b(et aussi|en m[eê]me temps|puis v[eé]rifie|compare avec|cherche sur|envoie|par mail|gmail|calendrier|agenda|comfyui|document|paperless)\b', q):
|
||||
return None
|
||||
return {'spotify':'spotify', 'homeassistant':'homeassistant,home_assistant', 'face_recognition':'face_recognition', 'proxmox':'proxmox', 'wazuh':'wazuh'}[matching[0]]
|
||||
|
||||
|
||||
# --------------------------------------------------
|
||||
@@ -381,6 +368,10 @@ def _call_hermes(
|
||||
"cli"
|
||||
]
|
||||
|
||||
route = _toolsets_for(prompt)
|
||||
if route and not session_id:
|
||||
cmd.extend(["--toolsets", route])
|
||||
|
||||
if session_id:
|
||||
cmd.extend([
|
||||
"--resume",
|
||||
@@ -448,7 +439,18 @@ def ask_hermes(text: str) -> str:
|
||||
):
|
||||
return _oneshot_legacy(prompt)
|
||||
|
||||
path = _session_file()
|
||||
base_path = _session_file()
|
||||
route = _toolsets_for(prompt)
|
||||
|
||||
if route:
|
||||
safe_route = re.sub(
|
||||
r"[^a-z0-9]+", "_", route.lower()
|
||||
).strip("_")
|
||||
path = base_path.with_name(
|
||||
f"{base_path.stem}.{safe_route}{base_path.suffix}"
|
||||
)
|
||||
else:
|
||||
path = base_path
|
||||
|
||||
# Empêche les appels concurrents
|
||||
with _REQUEST_LOCK, _session_lock(path):
|
||||
|
||||
Reference in New Issue
Block a user