outils.py — outils déterministes Phase 3 (22/10/2026)

–– coding: utf-8 ––

"""
MIRA — Outils déterministes
Fichier : outils.py
Phase : 3 — Outils déterministes branchés sur le noyau
Date : 18/10/2026

Rôle :
Fournir des réponses directes et fiables pour les intentions
qui ne nécessitent pas Phi-4 Mini (date, calcul, état système).
Appelé par noyau_phase3.py via executer_outil(intention, question).

Retourne :

  • Une chaîne de caractères si l’outil couvre l’intention
  • None si l’intention n’est pas couverte (le noyau continue)
    """

import os
import re
import shutil
from datetime import datetime, timezone

———————————————————-

JOURS ET MOIS EN FRANÇAIS

———————————————————-

JOURS_FR = {
0: "lundi", 1: "mardi", 2: "mercredi", 3: "jeudi",
4: "vendredi", 5: "samedi", 6: "dimanche"
}
MOIS_FR = {
1: "janvier", 2: "février", 3: "mars", 4: "avril",
5: "mai", 6: "juin", 7: "juillet", 8: "août",
9: "septembre", 10: "octobre", 11: "novembre", 12: "décembre"
}

==========================================================

OUTIL : DATE ET HEURE

==========================================================

def outil_date_heure(question):
"""
Répond aux questions sur la date et/ou l’heure.
Utilise l’horloge locale de la VM.
"""
maintenant = datetime.now()
q = question.lower()

jour_nom  = JOURS_FR[maintenant.weekday()]
jour_num  = maintenant.day
mois_nom  = MOIS_FR[maintenant.month]
annee     = maintenant.year
heure_str = maintenant.strftime("%H h %M")

if any(m in q for m in ["heure", "temps", "maintenant"]):
    if any(m in q for m in ["date", "jour", "aujourd"]):
        return (
            "Nous sommes le {} {} {} {}, il est {}.".format(
                jour_nom, jour_num, mois_nom, annee, heure_str
            )
        )
    return "Il est {}.".format(heure_str)

return (
    "Nous sommes le {} {} {} {}.".format(
        jour_nom, jour_num, mois_nom, annee
    )
)

==========================================================

OUTIL : CALCUL

==========================================================

def outil_calcul(question):
"""
Évalue une expression mathématique simple extraite de la question.
Opérations supportées : + – * / * ( )
Refuse toute expression non numérique (sécurité).
"""
expression = re.sub(r"[^0-9+-
/().,%\s]", "", question)
expression = expression.replace(",", ".").strip()

if not expression:
    return "Je n'ai pas trouvé d'expression à calculer dans ta question."

if re.search(r"[a-zA-Z_]", expression):
    return "Je ne peux calculer que des expressions numériques simples."

try:
    resultat = eval(expression, {"__builtins__": {}})
    if isinstance(resultat, float):
        if resultat == int(resultat):
            resultat = int(resultat)
        else:
            resultat = round(resultat, 6)
    return "{} = {}".format(expression, resultat)
except ZeroDivisionError:
    return "Division par zéro impossible."
except Exception:
    return "Je n'ai pas pu calculer cette expression."

==========================================================

OUTIL : ÉTAT SYSTÈME

==========================================================

def outil_etat_systeme(question):
"""
Retourne des informations basiques sur l’état du système :
espace disque, mémoire disponible (via /proc/meminfo).
"""
lignes = []

try:
    total, utilise, libre = shutil.disk_usage("/")
    lignes.append("Disque / : {:.1f} Go total, {:.1f} Go libres.".format(
        total / 1_073_741_824,
        libre / 1_073_741_824
    ))
except Exception as e:
    lignes.append("Disque : information indisponible ({}).".format(e))

try:
    meminfo = {}
    with open("/proc/meminfo", "r") as f:
        for ligne in f:
            cles = ligne.split()
            if len(cles) >= 2:
                meminfo[cles[0].rstrip(":")] = int(cles[1])

    total_ram = meminfo.get("MemTotal",     0) // 1024
    libre_ram = meminfo.get("MemAvailable", 0) // 1024
    lignes.append("RAM : {} Mo total, {} Mo disponibles.".format(
        total_ram, libre_ram
    ))
except Exception as e:
    lignes.append("RAM : information indisponible ({}).".format(e))

try:
    with open("/proc/loadavg", "r") as f:
        load = f.read().split()
    lignes.append("Charge CPU (1 min) : {}.".format(load[0]))
except Exception as e:
    lignes.append("CPU : information indisponible ({}).".format(e))

if lignes:
    return "État du système :\n" + "\n".join("  - " + l for l in lignes)
return "Impossible de lire l'état du système."

==========================================================

POINT D’ENTRÉE PRINCIPAL

==========================================================

def executer_outil(intention, question):
"""
Appelée par noyau_phase3.py.
Retourne une réponse (str) si l’intention est couverte,
None sinon (le noyau passe à l’étape suivante).
"""
if intention == "question_date":
return outil_date_heure(question)

if intention == "calcul":
    return outil_calcul(question)

if intention == "etat_systeme":
    return outil_etat_systeme(question)

return None

==========================================================

TEST AUTONOME

==========================================================

if name == "main":
print("=== TEST outils.py ===\n")

tests = [
    ("question_date", "quel jour sommes-nous ?"),
    ("question_date", "quelle heure est-il ?"),
    ("calcul",        "combien font 15 * 6 ?"),
    ("calcul",        "calcule 100 / 4 + 3"),
    ("calcul",        "combien font 2 ** 10 ?"),
    ("etat_systeme",  "quel est l'état du système ?"),
    ("inconnue",      "comment fonctionne Python ?"),
]

for intention, question in tests:
    reponse = executer_outil(intention, question)
    print("Intention : {}".format(intention))
    print("Question  : {}".format(question))
    print("Réponse   : {}".format(reponse))
    print()

print("=== TEST TERMINÉ ===")

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Défiler vers le haut