Integrate claude, improve selenium and support qemu #1

Open
mathben wants to merge 224 commits from develop into master
2 changed files with 77 additions and 0 deletions
Showing only changes of commit 3e53cbd47d - Show all commits

View file

@ -5372,6 +5372,43 @@ class TODO:
except OSError:
return False
@staticmethod
def _remote_port_open(host, port):
"""Quelqu'un écoute-t-il sur ce port DEPUIS l'hôte distant ?
True / False / None quand on n'a pas pu conclure (hôte injoignable,
pas de bash). On teste une vraie connexion TCP vers « localhost » et
non la table d'écoute : c'est exactement ce que fera le tunnel, y
compris le choix IPv4/IPv6 de la résolution.
"""
probe = (
f"exec 3<>/dev/tcp/localhost/{int(port)} && echo OPEN"
" || echo CLOSED"
)
try:
res = subprocess.run(
[
"ssh",
"-o",
"BatchMode=yes",
"-o",
"ConnectTimeout=10",
host,
f"bash -c {shlex.quote(probe)} 2>/dev/null",
],
capture_output=True,
text=True,
timeout=45,
)
except (OSError, subprocess.SubprocessError):
return None
out = res.stdout.strip()
if "OPEN" in out:
return True
if "CLOSED" in out:
return False
return None
def _deploy_port_forward(self):
"""Ouvre un tunnel SSH pour joindre un service distant depuis le
navigateur local.
@ -5397,6 +5434,22 @@ class TODO:
raw = input(f"{t('Local port (default:')} {remote}): ").strip()
local = raw if raw.isdigit() else remote
# Sonde AVANT d'ouvrir : sans elle, un service arrêté à l'autre bout
# ne se manifeste que par un mur de « channel N: open failed » à
# chaque requête du navigateur, qui ne dit pas d'où vient le refus.
print(f" {t('Checking the remote port...')}")
listening = self._remote_port_open(host, remote)
if listening is False:
print(
f" ⚠ {t('Nothing is listening on port')} {remote}"
f" {t('of')} {host}"
)
print(f" {t('Start the service there, or continue anyway.')}")
if not self._is_yes(input(t("Continue anyway? (y/N): "))):
return
elif listening is None:
print(f" ℹ️ {t('Could not probe the remote port; going on.')}")
if not self._port_is_free(local):
print(f" ⚠ {t('Local port already in use:')} {local}")
if not self._is_yes(input(t("Try anyway? (y/N): "))):

View file

@ -1419,6 +1419,30 @@ TRANSLATIONS = {
"fr": "Port local (défaut :",
"en": "Local port (default:",
},
"Checking the remote port...": {
"fr": "Vérification du port distant...",
"en": "Checking the remote port...",
},
"Nothing is listening on port": {
"fr": "Rien n'écoute sur le port",
"en": "Nothing is listening on port",
},
"of": {
"fr": "de",
"en": "of",
},
"Start the service there, or continue anyway.": {
"fr": "Démarrer le service là-bas, ou continuer quand même.",
"en": "Start the service there, or continue anyway.",
},
"Continue anyway? (y/N): ": {
"fr": "Continuer quand même ? (o/N, défaut : non) : ",
"en": "Continue anyway? (y/N, default: no): ",
},
"Could not probe the remote port; going on.": {
"fr": "Impossible de sonder le port distant ; on continue.",
"en": "Could not probe the remote port; going on.",
},
"Local port already in use:": {
"fr": "Port local déjà occupé :",
"en": "Local port already in use:",