feat(browser-test): persistent token + auto-reconnect + screenshot + smarter strategy (v0.7.9)

Four user-reported issues with the AI-driven browser test feature:

1. WS dies on every page reload / navigation (token was single-use,
   5 min TTL → AI loses session permanently).
2. AI can't see new pages opened by its actions (same root cause).
3. No screenshot capability — AI cannot capture page state visually.
4. AI burns ~150 tool calls for what's 5 human actions, mostly
   list_clickables loops.

Fixes:

- Token sliding TTL (60 min): ConsumeToken no longer deletes the
  token; it refreshes its expiration on each successful WS connect.
  Same token survives reload / re-paste / navigation as long as
  there's no 60-min idle gap.

- Snippet auto-reconnect: WS onclose schedules reconnect with
  500ms × attempt backoff (max ~2.5s). Handles transient drops,
  server restarts, and WS hiccups without user intervention. Full
  navigation kills the JS context and is unrecoverable from JS — but
  the user just re-pastes the snippet, same token works.

- New 'screenshot' action: snippet captures via SVG foreignObject +
  canvas → base64 PNG → sent back over the existing WS reply
  channel. Server decodes and writes to ~/.muyue/screenshots/
  <filename>.png (sanitized name, timestamp default). Filename
  characters limited to a safe charset to prevent path escape.
  Best-effort: external CSS / cross-origin images / iframes won't
  inline.

- Studio system prompt rewritten <browser_test_strategy>:
  - Explicit rule: don't list_clickables after every click
  - Action cost table (cheap vs expensive)
  - When to re-list (URL change, dialog, click-not-found only)
  - Standard final report format ✓ / ✗ / ⚠ / 📸

Also bundles v0.7.8 (cherry-picked): unsafe.Pointer(uintptr(hPC))
instead of unsafe.Pointer(&hPC) in UpdateProcThreadAttribute, so
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE is correctly applied and the
spawned shell attaches to the embedded xterm.js instead of opening
a separate external console window (regression fix from v0.7.6).

- internal/api/browsertest.go: token sliding, screenshot save,
  param schema, snippet rewrite, helpers
- internal/agent/prompts/studio_system.md: strategy rewrite
- internal/version/version.go: 0.7.7 → 0.7.9
- CHANGELOG.md: v0.7.9 entry covering all fixes
This commit is contained in:
Muyue
2026-04-27 15:07:36 +02:00
committed by Augustin
parent 5fd8cceabd
commit 97a25295fc
4 changed files with 243 additions and 34 deletions

View File

@@ -4,6 +4,26 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## v0.7.9
### Tests pilotés par l'IA — robustesse + captures d'écran
Quatre problèmes signalés par l'utilisateur :
1. **Connexion perdue à chaque reload / navigation**. Le token était à usage unique (5 min TTL) et tombait dès la première reconnexion → l'IA perdait totalement la session.
2. **Page nouvellement ouverte invisible à l'IA**. Conséquence du même bug ci-dessus + JS context détruit à la navigation.
3. **Pas de captures d'écran**. L'IA ne pouvait pas prouver visuellement l'état d'une page.
4. **L'IA se perd en boucle d'outils** : ~150 appels pour l'équivalent de 5 actions humaines, parce qu'elle re-listait les éléments cliquables après chaque clic.
**Fixes** :
- **Token réutilisable avec TTL coulissant** (`ConsumeToken` ne supprime plus le token, refresh la TTL à 60 min sur chaque utilisation). L'utilisateur peut re-coller le même snippet de l'onglet Tests sans avoir à régénérer un token, et la session reprend transparente.
- **Auto-reconnect dans le snippet** avec backoff exponentiel (500ms × tentative, max 5 tentatives = ~2,5s). Couvre les déconnexions transitoires (réseau, hibernation, redémarrage du serveur Muyue). Pour une vraie navigation full-page (URL change, JS context détruit), aucun JS ne peut survivre — l'utilisateur doit recoller le snippet, mais c'est immédiat car le token reste valide.
- **Nouvelle action `screenshot`** : le snippet capture la viewport (ou un sélecteur via `selector`) en SVG `foreignObject` + canvas, retourne un data URL base64. Le serveur décode et sauve dans `~/.muyue/screenshots/<filename>.png` (nom personnalisable via `filename`, sinon timestamp). Best-effort — CSS externes / images cross-origin / iframes peuvent ne pas apparaître ; les sélecteurs sont sanitisés (pas d'évasion vers d'autres dossiers).
- **Stratégie de test re-écrite dans le system prompt Studio** : règle d'or *"ne PAS ré-appeler `list_clickables` après chaque clic"*. Tableau des actions avec leur coût relatif (`summary` cher mais utile au début, `eval` ciblé > `list_clickables` complet, etc.). Format de rapport final standardisé (✓ / ✗ / ⚠ / 📸).
Inclut également **v0.7.8** (fix régression v0.7.6 : `unsafe.Pointer(uintptr(hPC))` au lieu de `&hPC` dans `UpdateProcThreadAttribute(PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE)` — corrige les terminaux qui s'ouvraient en fenêtre externe).
## v0.7.8
### Fix régression v0.7.6 : terminaux ouverts en fenêtre externe