Dinoer

Architecture

Le déroulement d'une campagne de recherche, et ce qui sort de votre machine par quelle porte, avec le fichier du code derrière chaque ligne.

Le déroulement d’une campagne de recherche

manifeste.json
     │  campagne.py
     ▼
SearXNG  ── requêtes
     ▼
collecte HTTP légère  ──►  navigateur réel (seulement si la page ne suffit pas)
     ▼
collecte.jsonl  +  operations.jsonl
     ▼
OpenCode  ── classement, puis le rapport
     ▼
rapport_<horodatage>.md
  1. Le manifeste est un fichier JSON de cibles : une query pour SearXNG, une url fixe, un produit (trouver la page qui est vraiment celle du produit) ou une table_reference (une liste de domaines de confiance pour un sujet). Seuls l’identifiant de la campagne et les cibles sont obligatoires.
  2. La découverte. Une cible query part vers l’instance SearXNG que vous avez configurée, qui interroge à son tour d’autres moteurs, sur lesquels Dinoer n’a pas la main.
  3. La collecte. Chaque page est récupérée par une simple requête HTTP, après lecture de son robots.txt. Seule une page dont le texte ne se lit pas ainsi passe à un vrai navigateur, un processus Playwright par page. Une cible qui échoue n’arrête pas les autres.
  4. Le corpus. Un collecte.jsonl par campagne, une ligne par page retenue, et operations.jsonl, qui consigne chaque tentative, réussie ou non.
  5. Le rapport. Les pages sont réordonnées (par période et par embeddings locaux, si le manifeste le demande), coupées à un budget de taille, puis confiées à OpenCode, qui rédige le corps de rapport_<horodatage>.md. Dinoer ajoute lui-même la liste des sources ; le modèle ne l’écrit jamais.

shot.py et rpa.py fonctionnent autrement : chaque appel est un processus à part, qui se termine dès qu’il a répondu. Pourquoi →

Ce qui sort de votre machine, et par quelle porte

QuoiOù cela partQui décideDans le code
Les requêtes de découvertel’instance SearXNG que vous avez configurée, qui interroge à son tour d’autres moteursvous, avec DINOER_SEARXNG_URLlib/searxng.py
Les requêtes de pageschaque site directement, son robots.txt lu d’abordles cibles de votre manifestelib/fetch_leger.py, rpa.py
Le texte collectéle modèle OpenCode que vous désignez, pour le rapport, pour l’extraction ciblée et pour choisir une page produit (les 1 500 premiers caractères de chaque candidate)vous, avec DINOER_OPENCODE_MODELlib/modeles.py, lib/synthese.py, lib/extraction.py, lib/selection_candidats.py
Un sujet, pour une table de référencele même modèle OpenCode, le sujet seul, quand aucune table n’existe encore pour luila cible table_referencelib/tables_reference.py
Les embeddingsvotre Ollama local, http://localhost:11434 : le texte reste sur la machine, sauf si vous dirigez DINOER_OLLAMA_URL ailleursvouslib/vector.py
Une notificationun serveur ntfy, https://ntfy.sh sauf si vous en indiquez un autre : l’identifiant de la campagne et le nombre de sources. Seulement si un topic ntfy est définivous, avec ntfy_topic, DINOER_NTFY_TOPIC, DINOER_NTFY_URLcampagne.py, lib/ntfy.py
Vos identifiantsnulle part : résolus dans le processus Playwright, depuis le répertoire chiffré—lib/repertoire_chiffre.py

Source : le code de la version 1.0.1, lu le 27 septembre 2026. Les modèles rangés sous opencode/ sont hébergés par leur fournisseur (opencode.ai/zen, d’après opencode models --verbose, OpenCode 1.18.32). Ce que le modèle a le droit de faire sur le web figure sur la page consacrée à la confiance.

Dans le détail