from duckduckgo_search import DDGS import subprocess import shlex import math def web_search(query: str, max_results: int = 5) -> list[dict]: out = [] with DDGS() as ddgs: for r in ddgs.text(query, max_results=max_results): out.append({"title": r.get("title"), "url": r.get("href"), "snippet": r.get("body")}) return out def electronics_ohm(V: float | None, I: float | None, R: float | None) -> dict: # résout V=I*R si une variable est None if [V, I, R].count(None) != 1: return {"error": "Donne exactement 2 valeurs (ex: V et R) et laisse l’autre à null."} if V is None: return {"V": I * R} if I is None: return {"I": V / R} return {"R": V / I} SAFE_COMMANDS = {"git", "docker", "docker-compose", "python", "pip", "ls", "cat", "grep", "tail", "journalctl"} def run_command(cmd: str) -> dict: # garde-fou minimal : n’autorise que certaines commandes parts = shlex.split(cmd) if not parts: return {"error": "Commande vide."} if parts[0] not in SAFE_COMMANDS: return {"error": f"Commande interdite: {parts[0]} (liste: {sorted(SAFE_COMMANDS)})"} try: p = subprocess.run(parts, capture_output=True, text=True, timeout=25) return {"returncode": p.returncode, "stdout": p.stdout[-4000:], "stderr": p.stderr[-4000:]} except Exception as e: return {"error": str(e)}