feat(browser-test): persistence + screenshots + smarter AI loop (v0.7.9) #19

Closed
Muyue wants to merge 2 commits from release/v0.7.9 into develop
Owner

4 problèmes utilisateur sur la fonctionnalité Tests pilotés par l'IA

Quand je suis en mode test, si l'IA recharge la page elle perd la connexion. Si elle ouvre une autre page elle perd aussi la possibilité de voir ce qu'elle a ouvert. Il lui faudrait la possibilité de prendre des captures d'écran à tout moment. Et pour les outils sur la page l'IA se perd, presque 150 utilisations pour seulement quelques actions humaines.

Bug 1 + 2 — connexion perdue à chaque reload / nouvelle page

Cause : token à usage unique (ConsumeToken supprimait le token à la 1ʳᵉ connexion) + TTL 5 min.

Fix :

  • Token réutilisable, TTL coulissante 60 min (ConsumeToken refresh la TTL au lieu de supprimer)
  • Auto-reconnect dans le snippet : ws.onclosesetTimeout(connect, 500 * retry) avec backoff (max ~2,5s). Couvre les drops transitoires.
  • Pour une vraie navigation full-page (JS context détruit), aucun JS ne peut survivre — l'utilisateur recolle le snippet, même token, session reprend.

Bug 3 — captures d'écran

Nouvelle action screenshot :

  • Le snippet capture via SVG foreignObject + canvas → base64 PNG
  • Renvoyé via le canal WS existant (pas de nouveau endpoint, pas d'enjeu CORS)
  • Le serveur décode et sauve dans ~/.muyue/screenshots/<filename>.png (nom personnalisable via filename, sinon timestamp)
  • Nom sanitisé pour éviter l'évasion de dossier
  • Best-effort : CSS externe / images cross-origin / iframes peuvent ne pas apparaître. C'est une capture DOM, pas une vraie capture pixel ; suffisant pour vérifier l'état d'une UI.

Bug 4 — l'IA boucle sur 150 appels

Cause : la stratégie disait list_clickables → click → list_clickables → click → ... à chaque action. Liste de 50+ éléments × 30 itérations = explosion du contexte.

Fix : <browser_test_strategy> re-écrite dans le system prompt Studio :

  • Règle d'or : ne PAS list_clickables après chaque clic
  • Tableau des actions avec coût relatif (summary cheap, eval ciblé > list_clickables complet)
  • Re-list seulement si URL change, dialog ouvert, ou click retourne element not found
  • Format de rapport final standardisé (✓ / ✗ / ⚠ / 📸)

Inclut aussi v0.7.8 (PR #18)

unsafe.Pointer(uintptr(hPC)) au lieu de unsafe.Pointer(&hPC) dans UpdateProcThreadAttribute — corrige les terminaux Windows qui s'ouvraient en fenêtre externe (régression v0.7.6). Cherry-pick depuis PR #18 ; PR #18 peut être fermée après merge de celui-ci.

Versioning

  • v0.7.7 → v0.7.9 (saut, le v0.7.8 est intégré ici)
  • CHANGELOG.md : entrées v0.7.9 + v0.7.8 conservées séparément

Test plan

  • manuel : test une page, déclencher un reload via clic AI → après recolle du snippet, l'IA reprend (même session id ne change pas)
  • manuel : screenshot avec et sans selector, fichier sauvé dans ~/.muyue/screenshots/
  • manuel : tâche de test exhaustif sur une UI à 50 boutons → vérifier que l'IA fait <50 appels d'outils au lieu de 150+
  • manuel Windows : terminaux PowerShell / cmd s'affichent dans le tab xterm.js (pas en fenêtre externe)
  • go vet + go test ./...
## 4 problèmes utilisateur sur la fonctionnalité Tests pilotés par l'IA > *Quand je suis en mode test, si l'IA recharge la page elle perd la connexion. Si elle ouvre une autre page elle perd aussi la possibilité de voir ce qu'elle a ouvert. Il lui faudrait la possibilité de prendre des captures d'écran à tout moment. Et pour les outils sur la page l'IA se perd, presque 150 utilisations pour seulement quelques actions humaines.* ### Bug 1 + 2 — connexion perdue à chaque reload / nouvelle page **Cause** : token à usage unique (`ConsumeToken` supprimait le token à la 1ʳᵉ connexion) + TTL 5 min. **Fix** : - Token réutilisable, **TTL coulissante 60 min** (`ConsumeToken` refresh la TTL au lieu de supprimer) - **Auto-reconnect dans le snippet** : `ws.onclose` → `setTimeout(connect, 500 * retry)` avec backoff (max ~2,5s). Couvre les drops transitoires. - Pour une vraie navigation full-page (JS context détruit), aucun JS ne peut survivre — l'utilisateur recolle le snippet, **même token, session reprend**. ### Bug 3 — captures d'écran Nouvelle action `screenshot` : - Le snippet capture via SVG `foreignObject` + canvas → base64 PNG - Renvoyé via le canal WS existant (pas de nouveau endpoint, pas d'enjeu CORS) - Le serveur décode et sauve dans `~/.muyue/screenshots/<filename>.png` (nom personnalisable via `filename`, sinon timestamp) - Nom sanitisé pour éviter l'évasion de dossier - Best-effort : CSS externe / images cross-origin / iframes peuvent ne pas apparaître. C'est une capture DOM, pas une vraie capture pixel ; suffisant pour vérifier l'état d'une UI. ### Bug 4 — l'IA boucle sur 150 appels **Cause** : la stratégie disait `list_clickables → click → list_clickables → click → ...` à chaque action. Liste de 50+ éléments × 30 itérations = explosion du contexte. **Fix** : `<browser_test_strategy>` re-écrite dans le system prompt Studio : - **Règle d'or** : ne PAS `list_clickables` après chaque clic - Tableau des actions avec **coût relatif** (`summary` cheap, `eval` ciblé > `list_clickables` complet) - Re-list seulement si URL change, dialog ouvert, ou `click` retourne `element not found` - Format de rapport final standardisé (✓ / ✗ / ⚠ / 📸) ### Inclut aussi v0.7.8 (PR #18) `unsafe.Pointer(uintptr(hPC))` au lieu de `unsafe.Pointer(&hPC)` dans `UpdateProcThreadAttribute` — corrige les terminaux Windows qui s'ouvraient en fenêtre externe (régression v0.7.6). Cherry-pick depuis PR #18 ; **PR #18 peut être fermée** après merge de celui-ci. ### Versioning - v0.7.7 → v0.7.9 (saut, le v0.7.8 est intégré ici) - CHANGELOG.md : entrées v0.7.9 + v0.7.8 conservées séparément ### Test plan - [ ] manuel : test une page, déclencher un reload via clic AI → après recolle du snippet, l'IA reprend (même session id ne change pas) - [ ] manuel : screenshot avec et sans `selector`, fichier sauvé dans `~/.muyue/screenshots/` - [ ] manuel : tâche de test exhaustif sur une UI à 50 boutons → vérifier que l'IA fait <50 appels d'outils au lieu de 150+ - [ ] manuel Windows : terminaux PowerShell / cmd s'affichent dans le tab xterm.js (pas en fenêtre externe) - [ ] go vet + go test ./...
Muyue added 2 commits 2026-04-27 13:08:28 +00:00
User reported regression introduced in v0.7.6: PowerShell / cmd open
in a separate external console window instead of attaching to the
xterm.js tab (v0.7.5 worked).

Root cause: the ConPTY wiring used
  attrList.Update(PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
                  unsafe.Pointer(&hPC),    // ← wrong
                  unsafe.Sizeof(hPC))

The PSEUDOCONSOLE attribute is a Win32 API quirk: lpValue must be
the HPCON *value* (cast to PVOID), not a pointer to the local
variable holding the handle. With &hPC the kernel reads garbage,
silently drops the attribute, and CreateProcessW spawns the child
with a fresh console — hence the external window.

Fix is one line:
  unsafe.Pointer(uintptr(hPC))

Confirmed against Microsoft's EchoCon sample and Go libraries that
work in production (UserExistsError/conpty, aymanbagabas/go-pty).

- internal/version/version.go: 0.7.7 → 0.7.8
- CHANGELOG.md: v0.7.8 entry with the diagnostic write-up
feat(browser-test): persistent token + auto-reconnect + screenshot + smarter strategy (v0.7.9)
All checks were successful
PR Check / check (pull_request) Successful in 1m3s
83dce00265
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
Muyue closed this pull request 2026-04-27 13:49:44 +00:00
Muyue deleted branch release/v0.7.9 2026-04-27 13:49:51 +00:00
All checks were successful
PR Check / check (pull_request) Successful in 1m3s

Pull request closed

Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Muyue/MuyueWorkspace#19