bots-garden/mini-mepublic Fork
⑂ v1.0.3
Commits
⬇ Clone ▾
git clone https://git.rickub.com/bots-garden/mini-me.git
git clone ssh://git@rickub.com/bots-garden/mini-me.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP
🛟 Updated. 0d48ec0 · on v1.0.3 · k33g · Sep 29, 2026
fetch-content-tool.md · 49 lines · 5.8 KBmarkdown
Blame HistoryOpen raw

L'outil fetch_content — explication

De quoi s'agit-il ?

fetch_content donne au modèle une capacité qu'il n'exerçait jusqu'ici que maladroitement : lire une page web. Avec bash seul, un modèle lance curl, reçoit des centaines de kilo-octets de HTML (scripts, styles, menus, code de suivi) et soit y noie sa fenêtre de contexte, soit résume une page qu'il n'a jamais vraiment vue. fetch_content télécharge la page, jette ce qui n'est pas du contenu et rend du Markdown : le format qu'un modèle de langage lit le mieux, et celui qu'un utilisateur peut conserver.

Le travail est coupé en deux. internal/webmd est un paquet Go ordinaire en trois étapes — Fetcher.Fetch, Clean, Convert — qui ne sait rien des modèles. internal/tools/fetchcontent.go est la fine couche d'outil autour : arguments, affichage, permission, et le texte que reçoit le modèle.

Pourquoi un outil intégré, et pas le serveur MCP fetch

On peut déjà brancher un serveur MCP fetch sur mm. L'outil intégré existe pour ce qu'un tel serveur ne garantit pas :

  • Il fonctionne sans rien installer d'autre. Ni Node, ni Python, ni passerelle : la conversion est dans le binaire.
  • Il sait enregistrer sans renvoyer. « Sauve-le dans hello.txt, ne l'affiche pas » est une demande courante, et un outil qui renvoie toujours la page fait payer au modèle toute la page dans son contexte rien que pour la recopier dans un fichier — ce qu'un petit modèle local fait mal de toute façon. output écrit le fichier directement et ne renvoie qu'une ligne.
  • Ses règles de conversion sont les nôtres. La spécification qu'il suit (voir la référence) fixe titres, listes, tableaux, échappement ; les tests les verrouillent.

Il s'appelle fetch_content, pas fetch, pour ne jamais entrer en collision avec un outil MCP de ce nom.

Pourquoi la conversion est écrite ici

Une bibliothèque comme html-to-markdown a été envisagée. La spécification demande des comportements que ces bibliothèques n'ont pas ou rendent malaisés : tableaux complexes gardés en HTML brut ou aplatis à la demande, un nettoyage guidé par les rôles et les mots de classe avec une protection pour les conteneurs de mise en page, des liens résolus contre l'URL finale, une sortie stricte « un seul retour à la ligne final, pas de préambule ». Plier un convertisseur généraliste à tout cela aurait coûté à peu près autant que d'écrire ces quelques centaines de lignes, en ajoutant une dépendance dont les comportements par défaut peuvent changer sous nos pieds. L'analyse elle-même n'est pas la nôtre : golang.org/x/net/html est le parseur HTML5, donc un HTML cassé est réparé exactement comme un navigateur le répare.

Pourquoi le robots.txt est respecté

mm récupère pour le compte d'une personne, une page à la fois — plus proche d'un navigateur que d'un robot d'indexation. Il respecte pourtant le robots.txt, parce que la demande l'exigeait et parce qu'un agent qui ignore les souhaits déclarés d'un site se conduit mal, si peu de requêtes qu'il envoie. Il s'annonce comme mm/<version>, pour qu'un site puisse le désigner par son nom.

Les règles suivent la RFC 9309, y compris ses recoins prudents : un site dont le robots.txt répond par une erreur serveur, ou est injoignable, est considéré comme fermé — le choix de la RFC, et la seule lecture sûre de « nous n'avons pas pu demander ». Chaque redirection est vérifiée aussi, pour qu'une redirection ne mène pas vers un chemin interdit.

Pourquoi un échec est un texte avec un numéro

Tous les outils de mm renvoient leurs échecs en texte, pour que le modèle les lise et réagisse. fetch_content y ajoute le code d'erreur de sa spécification (1 conversion, 2 entrée, 3 usage), parce que les trois appellent des réactions différentes : corriger l'appel (3), abandonner ou essayer une autre page (2), ou dire à l'utilisateur que ce n'est pas une page web (1). Un modèle qui lit error 2 (input) — … robots.txt does not allow "mm" n'a aucune raison d'essayer curl ensuite.

Des choix qui échangent de l'exactitude contre de la sûreté

  • Désactivé par défaut. C'est le seul outil intégré qui accède au réseau ; un opérateur l'active en connaissance de cause.
  • Limites. 30 secondes, 5 Mio, 10 redirections : un appel d'outil ne doit ni bloquer un tour ni remplir la mémoire.
  • Encodage. L'encodage déclaré l'emporte (BOM, puis en-tête HTTP, puis <meta>) ; quand rien n'est déclaré, de l'UTF-8 valide est lu comme de l'UTF-8 et tout le reste comme du windows-1252, le défaut historique du web.
  • Les images en URI data: sont réduites à leur texte alternatif : des kilo-octets de base64 ne servent à aucun lecteur, humain ou modèle.

Limites connues

  • Le nettoyage est heuristique. Il retire la navigation, les publicités et les bannières signalées comme telles ; une publicité sans classe ni rôle révélateur reste, et un nom de classe inhabituel peut, rarement, retirer du contenu. Tout ce qui enveloppe un main, un article ou un h1 est protégé.
  • Les éléments en ligne qu'une page ne sépare que par du CSS ressortent collés : des étiquettes rendues par <a>go</a><a>tui</a> donnent gotui.
  • Les pages construites par JavaScript dans le navigateur ont peu de contenu dans leur HTML ; fetch_content n'exécute pas de script.
  • Seul le HTML est converti : un PDF ou un document JSON est refusé avec error 1.

Comment il s'insère dans le reste

fetch_content suit le même contrat que les autres outils (voir l'architecture) : une ligne d'affichage dans le terminal, un événement avec un genre (fetch) pour ACP et la fenêtre, une demande de permission seulement quand il écrit un fichier, et un enregistrement dans le détecteur de boucle. Sa sortie passe par la même troncature maxOutput que bash.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# L'outil `fetch_content` — explication

## De quoi s'agit-il ?

`fetch_content` donne au modèle une capacité qu'il n'exerçait jusqu'ici que maladroitement : lire une page web. Avec `bash` seul, un modèle lance `curl`, reçoit des centaines de kilo-octets de HTML (scripts, styles, menus, code de suivi) et soit y noie sa fenêtre de contexte, soit résume une page qu'il n'a jamais vraiment vue. `fetch_content` télécharge la page, jette ce qui n'est pas du contenu et rend du Markdown : le format qu'un modèle de langage lit le mieux, et celui qu'un utilisateur peut conserver.

Le travail est coupé en deux. `internal/webmd` est un paquet Go ordinaire en trois étapes — `Fetcher.Fetch`, `Clean`, `Convert` — qui ne sait rien des modèles. `internal/tools/fetchcontent.go` est la fine couche d'outil autour : arguments, affichage, permission, et le texte que reçoit le modèle.

## Pourquoi un outil intégré, et pas le serveur MCP `fetch`

On peut déjà brancher un serveur MCP `fetch` sur `mm`. L'outil intégré existe pour ce qu'un tel serveur ne garantit pas :

- **Il fonctionne sans rien installer d'autre.** Ni Node, ni Python, ni passerelle : la conversion est dans le binaire.
- **Il sait enregistrer sans renvoyer.** « Sauve-le dans hello.txt, ne l'affiche pas » est une demande courante, et un outil qui renvoie toujours la page fait payer au modèle toute la page dans son contexte rien que pour la recopier dans un fichier — ce qu'un petit modèle local fait mal de toute façon. `output` écrit le fichier directement et ne renvoie qu'une ligne.
- **Ses règles de conversion sont les nôtres.** La spécification qu'il suit (voir la référence) fixe titres, listes, tableaux, échappement ; les tests les verrouillent.

Il s'appelle `fetch_content`, pas `fetch`, pour ne jamais entrer en collision avec un outil MCP de ce nom.

## Pourquoi la conversion est écrite ici

Une bibliothèque comme html-to-markdown a été envisagée. La spécification demande des comportements que ces bibliothèques n'ont pas ou rendent malaisés : tableaux complexes gardés en HTML brut *ou* aplatis à la demande, un nettoyage guidé par les rôles et les mots de classe avec une protection pour les conteneurs de mise en page, des liens résolus contre l'URL finale, une sortie stricte « un seul retour à la ligne final, pas de préambule ». Plier un convertisseur généraliste à tout cela aurait coûté à peu près autant que d'écrire ces quelques centaines de lignes, en ajoutant une dépendance dont les comportements par défaut peuvent changer sous nos pieds. L'analyse elle-même n'est pas la nôtre : `golang.org/x/net/html` est le parseur HTML5, donc un HTML cassé est réparé exactement comme un navigateur le répare.

## Pourquoi le robots.txt est respecté

`mm` récupère pour le compte d'une personne, une page à la fois — plus proche d'un navigateur que d'un robot d'indexation. Il respecte pourtant le `robots.txt`, parce que la demande l'exigeait et parce qu'un agent qui ignore les souhaits déclarés d'un site se conduit mal, si peu de requêtes qu'il envoie. Il s'annonce comme `mm/<version>`, pour qu'un site puisse le désigner par son nom.

Les règles suivent la RFC 9309, y compris ses recoins prudents : un site dont le `robots.txt` répond par une erreur serveur, ou est injoignable, est considéré comme fermé — le choix de la RFC, et la seule lecture sûre de « nous n'avons pas pu demander ». Chaque redirection est vérifiée aussi, pour qu'une redirection ne mène pas vers un chemin interdit.

## Pourquoi un échec est un texte avec un numéro

Tous les outils de `mm` renvoient leurs échecs en texte, pour que le modèle les lise et réagisse. `fetch_content` y ajoute le code d'erreur de sa spécification (1 conversion, 2 entrée, 3 usage), parce que les trois appellent des réactions différentes : corriger l'appel (3), abandonner ou essayer une autre page (2), ou dire à l'utilisateur que ce n'est pas une page web (1). Un modèle qui lit `error 2 (input) — … robots.txt does not allow "mm"` n'a aucune raison d'essayer `curl` ensuite.

## Des choix qui échangent de l'exactitude contre de la sûreté

- **Désactivé par défaut.** C'est le seul outil intégré qui accède au réseau ; un opérateur l'active en connaissance de cause.
- **Limites.** 30 secondes, 5 Mio, 10 redirections : un appel d'outil ne doit ni bloquer un tour ni remplir la mémoire.
- **Encodage.** L'encodage déclaré l'emporte (BOM, puis en-tête HTTP, puis `<meta>`) ; quand rien n'est déclaré, de l'UTF-8 valide est lu comme de l'UTF-8 et tout le reste comme du windows-1252, le défaut historique du web.
- **Les images en URI `data:`** sont réduites à leur texte alternatif : des kilo-octets de base64 ne servent à aucun lecteur, humain ou modèle.

## Limites connues

- Le nettoyage est heuristique. Il retire la navigation, les publicités et les bannières signalées comme telles ; une publicité sans classe ni rôle révélateur reste, et un nom de classe inhabituel peut, rarement, retirer du contenu. Tout ce qui enveloppe un `main`, un `article` ou un `h1` est protégé.
- Les éléments en ligne qu'une page ne sépare que par du CSS ressortent collés : des étiquettes rendues par `<a>go</a><a>tui</a>` donnent `gotui`.
- Les pages construites par JavaScript dans le navigateur ont peu de contenu dans leur HTML ; `fetch_content` n'exécute pas de script.
- Seul le HTML est converti : un PDF ou un document JSON est refusé avec `error 1`.

## Comment il s'insère dans le reste

`fetch_content` suit le même contrat que les autres outils (voir [l'architecture](architecture.md)) : une ligne d'affichage dans le terminal, un événement avec un genre (`fetch`) pour ACP et la fenêtre, une demande de permission seulement quand il écrit un fichier, et un enregistrement dans le détecteur de boucle. Sa sortie passe par la même troncature `maxOutput` que `bash`.