Mode code : la capture d'écran sans accès internet, bornée au local

Le modèle cherchait à vérifier visuellement son travail, ne trouvait pas
web_screenshot (offert seulement avec l'accès internet), en concluait
« pas de Chromium local » et partait installer puppeteer — alors qu'un
Chromium headless est dans l'image depuis toujours.

L'outil est donc offert aussi au mode code sans internet, mais borné aux
adresses locales (localhost, 127.0.0.1, ::1, *.localhost) : photographier
son propre serveur de dev est une vérification locale, pas une sortie sur
le web — l'interrupteur d'accès internet garde tout son sens. Le prompt
du builder dit explicitement que le navigateur est déjà là et qu'il ne
faut installer aucun paquet de navigateur.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Opus 5 committed 2026-08-19 08:08:41 +02:00
1 parent 608e7f7038
commit 0430aa2281
3 files changed
+37 -9

No files matched your search

+25 -1
View File
@@ -20,6 +20,7 @@ import (
"encoding/json"
"fmt"
"net/http"
neturl "net/url"
"os"
"os/exec"
"path/filepath"
@@ -242,7 +243,7 @@ func safeSlug(s string) string {
return s
}
func toolWebScreenshot(args map[string]any) string {
func toolWebScreenshot(args map[string]any, caps Caps) string {
bin := playwrightBin()
if bin == "" {
return "[erreur] Playwright n'est pas installé dans cette image (bâtie avec PLAYWRIGHT=0)."
@@ -255,6 +256,13 @@ func toolWebScreenshot(args map[string]any) string {
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
return "[erreur] url invalide : elle doit commencer par http:// ou https://"
}
// Accès internet coupé : la capture reste offerte au MODE CODE, mais bornée
// aux adresses locales — voir sa propre page de dev, pas le web. Sans cette
// borne, l'outil rouvrirait par la fenêtre ce que l'interrupteur ferme.
if !caps.Internet && !isLocalURL(url) {
return "[refusé] L'accès internet est coupé : la capture ne marche que sur une adresse locale " +
"(localhost / 127.0.0.1), par exemple ton serveur de dev. Active l'accès internet pour le web."
}
// width n'est plus déclaré dans le schéma (budget de préambule), mais reste
// honoré s'il arrive quand même : un modèle qui l'invente obtient le
// comportement attendu plutôt qu'un paramètre ignoré en silence.
@@ -397,3 +405,19 @@ func lastLines(s string, n int) string {
}
return strings.Join(keep, " · ")
}
// isLocalURL : l'adresse désigne-t-elle cette machine ? Sert de borne quand
// l'accès internet est coupé mais que le mode code doit pouvoir photographier
// son propre serveur de dev.
func isLocalURL(raw string) bool {
u, err := neturl.Parse(raw)
if err != nil {
return false
}
host := u.Hostname()
switch host {
case "localhost", "127.0.0.1", "::1", "0.0.0.0":
return true
}
return strings.HasSuffix(host, ".localhost")
}