Compétence de navigation Dev Browser
Automatisation du navigateur qui maintient l'état de la page entre les exécutions de scripts. Écrivez des scripts courts et ciblés pour accomplir les tâches de manière incrémentale. Une fois que vous avez validé une partie d'un workflow et qu'il y a un travail répétitif à effectuer, vous pouvez écrire un script pour effectuer le travail répétitif en une seule exécution.
Choisir votre approche
- Sites locaux/sources disponibles : Lisez d'abord le code source pour écrire les sélecteurs directement
- Mises en page de page inconnues : Utilisez
getAISnapshot()pour découvrir les éléments etselectSnapshotRef()pour interagir avec eux - Retour visuel : Prenez des captures d'écran pour voir ce que l'utilisateur voit
Configuration
Deux modes disponibles. Demandez à l'utilisateur si vous n'êtes pas sûr de celui à utiliser.
Mode autonome (par défaut)
Lance un nouveau navigateur Chromium pour des sessions d'automatisation fraîches.
./skills/dev-browser/server.sh &
Ajoutez le drapeau --headless si l'utilisateur le demande. Attendez le message Ready avant d'exécuter les scripts.
Mode extension
Se connecte au navigateur Chrome existant de l'utilisateur. Utilisez-le lorsque :
- L'utilisateur est déjà connecté à des sites et souhaite que vous fassiez des choses derrière une expérience authentifiée qui n'est pas du développement local.
- L'utilisateur vous demande d'utiliser l'extension
Important : Le flux principal reste le même. Vous créez des pages nommées dans son navigateur.
Démarrez le serveur relais :
cd skills/dev-browser && npm i && npm run start-extension &
Attendez En attente de la connexion de l'extension... suivi de Extension connectée dans la console. Pour savoir qu'un client s'est connecté et que le navigateur est prêt à être contrôlé.
Workflow :
- Les scripts appellent
client.page("nom")comme en mode normal pour créer de nouvelles pages / se connecter à des pages existantes. - L'automatisation s'exécute dans la session de navigateur réelle de l'utilisateur
Si l'extension ne s'est pas encore connectée, dites à l'utilisateur de la lancer et de l'activer. Lien de téléchargement : https://github.com/SawyerHood/dev-browser/releases
Écrire des scripts
Exécutez tous les scripts depuis le répertoire
skills/dev-browser/. L'alias d'importation@/nécessite la configuration de ce répertoire.
Exécutez les scripts en ligne en utilisant heredocs :
cd skills/dev-browser && npx tsx <<'EOF'
import { connect, waitForPageLoad } from "@/client.js";
const client = await connect();
// Créer une page avec une taille de fenêtre personnalisée (optionnel)
const page = await client.page("example", { viewport: { width: 1920, height: 1080 } });
await page.goto("https://example.com");
await waitForPageLoad(page);
console.log({ title: await page.title(), url: page.url() });
await client.disconnect();
EOF
Écrivez dans des fichiers tmp/ uniquement lorsque le script nécessite une réutilisation, est complexe ou que l'utilisateur le demande explicitement.
Principes clés
- Scripts courts : Chaque script fait UNE chose (naviguer, cliquer, remplir, vérifier)
- Évaluer l'état : Enregistrez/retournez l'état à la fin pour décider des prochaines étapes
- Noms de pages descriptifs : Utilisez
"checkout","login", pas"main" - Déconnexion pour sortir :
await client.disconnect()- les pages persistent sur le serveur - JS simple dans evaluate :
page.evaluate()s'exécute dans le navigateur - pas de syntaxe TypeScript
Boucle de workflow
Suivez ce modèle pour les tâches complexes :
- Écrivez un script pour effectuer une action
- Exécutez-le et observez la sortie
- Évaluez - cela a-t-il fonctionné ? Quel est l'état actuel ?
- Décidez - la tâche est-elle terminée ou avons-nous besoin d'un autre script ?
- Répétez jusqu'à ce que la tâche soit terminée
Pas de TypeScript dans le contexte du navigateur
Le code passé à page.evaluate() s'exécute dans le navigateur, qui ne comprend pas TypeScript :
// ✅ Correct : JavaScript simple
const text = await page.evaluate(() => {
return document.body.innerText;
});
// ❌ Faux : la syntaxe TypeScript échouera à l'exécution
const text = await page.evaluate(() => {
const el: HTMLElement = document.body; // L'annotation de type plante dans le navigateur !
return el.innerText;
});
Extraction de données
Pour extraire de grands ensembles de données, interceptez et rejouez les requêtes réseau plutôt que de faire défiler le DOM. Voir references/scraping.md pour le guide complet couvrant la capture de requêtes, la découverte de schémas et la relecture d'API paginée.
API Client
const client = await connect();
// Obtenir ou créer une page nommée (le viewport ne s'applique qu'aux nouvelles pages)
const page = await client.page("nom");
const pageWithSize = await client.page("nom", { viewport: { width: 1920, height: 1080 } });
const pages = await client.list(); // Lister tous les noms de pages
await client.close("nom"); // Fermer une page
await client.disconnect(); // Se déconnecter (les pages persistent)
// Méthodes ARIA Snapshot
const snapshot = await client.getAISnapshot("nom"); // Obtenir l'arbre d'accessibilité
const element = await client.selectSnapshotRef("nom", "e5"); // Obtenir un élément par référence
L'objet page est une Page Playwright standard.
Attente
import { waitForPageLoad } from "@/client.js";
await waitForPageLoad(page); // Après la navigation
await page.waitForSelector(".results"); // Pour des éléments spécifiques
await page.waitForURL("**/success"); // Pour une URL spécifique
Inspection de l'état de la page
Captures d'écran
await page.screenshot({ path: "tmp/screenshot.png" });
await page.screenshot({ path: "tmp/full.png", fullPage: true });
ARIA Snapshot (Découverte d'éléments)
Utilisez getAISnapshot() pour découvrir les éléments de la page. Retourne un arbre d'accessibilité au format YAML :
- banner:
- link "Hacker News" [ref=e1]
- navigation:
- link "new" [ref=e2]
- main:
- list:
- listitem:
- link "Titre de l'article" [ref=e8]
- link "328 commentaires" [ref=e9]
- contentinfo:
- textbox [ref=e10]
- /placeholder: "Rechercher"
Interprétation des refs :
[ref=eN]- Référence d'élément pour l'interaction (éléments visibles et cliquables uniquement)[checked],[disabled],[expanded]- États des éléments[level=N]- Niveau de titre/url:,/placeholder:- Propriétés des éléments
Interagir avec les refs :
const snapshot = await client.getAISnapshot("hackernews");
console.log(snapshot); // Trouver le ref dont vous avez besoin
const element = await client.selectSnapshotRef("hackernews", "e2");
await element.click();
Récupération d'erreur
L'état de la page persiste après les échecs. Déboguez avec :
cd skills/dev-browser && npx tsx <<'EOF'
import { connect } from "@/client.js";
const client = await connect();
const page = await client.page("hackernews");
await page.screenshot({ path: "tmp/debug.png" });
console.log({
url: page.url(),
title: await page.title(),
bodyText: await page.textContent("body").then((t) => t?.slice(0, 200)),
});
await client.disconnect();
EOF