Commit e0fe61f
feat(mcp): snapshot tool + run_code return/console capture + storage state + HTML cleanup (#5537)
* feat(mcp): snapshot tool, run_code return/console capture, storage state, HTML cleanup
Adds a `snapshot` MCP tool that captures the current browser state without
performing any action. `run_code` now also returns the value the code
produced and captures `console.*` output (level + message + relative time)
using the existing `safeStringify` from lib/utils.js with a `truncateString`
helper, so models can use debug statements and inspect return values.
Captures cookies + localStorage via Playwright's `grabStorageState()` (with
a `grabCookie + executeScript` fallback for Puppeteer/WebDriver),
normalized to a single shape and saved as `_storage.json` alongside the
other artifacts.
Centralizes the artifact-grab + trace-record glue:
- New `lib/utils/captureSnapshot.js` is the single funnel for HTML / ARIA /
screenshot / console / storage capture.
- New `lib/utils/trace.js` holds shared helpers (`pickActingHelper`,
`traceDirFor`, `snapshotDirFor`, `artifactLinks`, `artifactsToFileUrls`)
used by `aiTrace`, `pageInfo`, and the MCP server.
- aiTrace and pageInfo now go through the same funnel — pageInfo's three
serial recorder steps collapse to one delegated capture.
HTML processing pipeline (`formatHtml` in `lib/html.js`): minify ->
cleanHtml -> beautify. `cleanHtml` (new) drops `<script>` (no src) /
`<style>` / `<noscript>`, strips trash class names (Tailwind utilities,
hashed/scoped/framework-generated), and removes inline `style=""`. Built
on `js-beautify` (already a dep) instead of a hand-rolled pretty-printer.
Browser-log normalization fixes a latent bug where `JSON.stringify` was
called on Playwright `ConsoleMessage` objects, producing files full of
empty objects. Logs are now coerced to plain `{type, text}` (or kept as
strings for WebDriver) before serialization.
`safeStringify` in lib/utils.js is extended to also coerce
Function/Error/BigInt/Symbol values — universal improvements that close
a JSON.stringify(BigInt) crash and don't regress the existing 12 mocha
serialization tests.
Tests: 72 unit tests passing (12 circular_reference + 23 html (incl. new
`#cleanHtml`, `#formatHtml`, `#isTrashClass` describes) + 13 aiTrace + 32
mcp + 1 pending). Docs updated in `docs/mcp.md` and `docs/aitrace.md`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(utils): unify captureSnapshot + trace into lib/utils/trace.js
Both files belonged to the same flow (capture artifacts -> render trace.md).
Splitting them across two files made the import sites awkward, so they're
now consolidated:
- `lib/utils/captureSnapshot.js` deleted; its `captureSnapshot`,
`normalizeBrowserLogs`, and `captureStorageState` moved into
`lib/utils/trace.js`.
- `writeTraceMarkdown` (was inlined in `bin/mcp-server.js`) moved into
`lib/utils/trace.js` too — it's the same trace-record concern.
- All three call sites (`bin/mcp-server.js`, `lib/plugin/aiTrace.js`,
`lib/plugin/pageInfo.js`) now import from a single module.
- Stale `writeFileSync` import dropped from `bin/mcp-server.js`.
72 unit tests still passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(utils): add unit coverage for trace.js + safeStringify extensions + truncateString
49 new test cases across two files:
- `test/unit/utils/trace_test.js` (new, 37 cases) — direct coverage of
every export from `lib/utils/trace.js`:
- `pickActingHelper` (all 3 paths)
- `traceDirFor` (determinism, uniqueness, sanitization, missing args)
- `snapshotDirFor` (uniqueness, embedded timestamp)
- `artifactLinks` (each artifact, console-count override, storage
counts, custom indent, empty input, ordering invariant)
- `fileToUrl` / `artifactsToFileUrls`
- `writeTraceMarkdown` (golden output, error block, optional commands,
default `file`)
- `captureSnapshot` (default options, full opt-out matrix, fullPage,
formatHtml integration, ConsoleMessage normalization, Playwright
grabStorageState path, Puppeteer/WebDriver fallback path, empty
storage handled, missing helper methods, error swallowing, default
prefix)
- `test/unit/circular_reference_test.js` (extended, 12 new cases):
- `safeStringify` Function/BigInt/Symbol/Error coercions including
nested mixed types (BigInt was a real bug; JSON.stringify(BigInt)
used to throw and trigger the legacy fallback path)
- `truncateString` under / equal / over maxBytes, non-string coercion,
empty string
Total unit suite: 121 passing (was 72).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(trace): use pathToFileURL for Windows-safe URLs; scan raw HTML in pageInfo
- Replace `file://${path}` template literals in lib/utils/trace.js
fileToUrl() and bin/mcp-server.js with pathToFileURL().href so paths
like `C:\foo\bar` are encoded correctly on Windows.
- captureSnapshot now also returns out.htmlRaw (pre-cleanHtml source) so
consumers can scan classes that the trash-class filter would strip.
- pageInfo's error-class scan now reads htmlRaw, restoring detection of
errorClasses containing digits/prefixes like `text-error` or `alert-1`.
---------
Co-authored-by: DavertMik <davert@testomat.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 87a25ad commit e0fe61f
11 files changed
Lines changed: 1308 additions & 236 deletions
File tree
- bin
- docs
- lib
- plugin
- utils
- test/unit
- utils
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
8 | 16 | | |
9 | | - | |
| 17 | + | |
10 | 18 | | |
11 | 19 | | |
12 | | - | |
13 | 20 | | |
14 | 21 | | |
15 | | - | |
| 22 | + | |
16 | 23 | | |
17 | 24 | | |
18 | 25 | | |
| |||
224 | 231 | | |
225 | 232 | | |
226 | 233 | | |
227 | | - | |
228 | | - | |
229 | | - | |
230 | | - | |
231 | | - | |
232 | | - | |
233 | | - | |
234 | | - | |
235 | | - | |
| 234 | + | |
| 235 | + | |
236 | 236 | | |
237 | 237 | | |
238 | 238 | | |
| |||
337 | 337 | | |
338 | 338 | | |
339 | 339 | | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
340 | 351 | | |
341 | 352 | | |
342 | 353 | | |
| |||
416 | 427 | | |
417 | 428 | | |
418 | 429 | | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
419 | 463 | | |
420 | 464 | | |
421 | 465 | | |
422 | 466 | | |
423 | 467 | | |
424 | 468 | | |
425 | 469 | | |
426 | | - | |
| 470 | + | |
427 | 471 | | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
428 | 502 | | |
429 | 503 | | |
430 | | - | |
| 504 | + | |
431 | 505 | | |
432 | 506 | | |
433 | 507 | | |
434 | 508 | | |
435 | 509 | | |
436 | 510 | | |
437 | | - | |
438 | | - | |
439 | | - | |
440 | | - | |
441 | | - | |
442 | | - | |
443 | | - | |
444 | | - | |
445 | | - | |
446 | | - | |
447 | | - | |
448 | | - | |
449 | | - | |
450 | | - | |
451 | | - | |
452 | | - | |
453 | | - | |
454 | | - | |
455 | | - | |
456 | | - | |
457 | | - | |
458 | | - | |
459 | | - | |
460 | | - | |
461 | | - | |
462 | | - | |
463 | | - | |
464 | | - | |
465 | | - | |
466 | | - | |
467 | | - | |
468 | | - | |
469 | | - | |
470 | | - | |
471 | | - | |
472 | | - | |
473 | | - | |
474 | | - | |
475 | | - | |
476 | | - | |
477 | | - | |
478 | | - | |
479 | | - | |
480 | | - | |
481 | 511 | | |
482 | 512 | | |
483 | 513 | | |
484 | 514 | | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
485 | 529 | | |
486 | 530 | | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
487 | 556 | | |
488 | 557 | | |
489 | 558 | | |
| |||
549 | 618 | | |
550 | 619 | | |
551 | 620 | | |
| 621 | + | |
552 | 622 | | |
553 | 623 | | |
554 | 624 | | |
555 | 625 | | |
556 | | - | |
| 626 | + | |
557 | 627 | | |
558 | 628 | | |
| 629 | + | |
559 | 630 | | |
560 | 631 | | |
561 | 632 | | |
562 | | - | |
563 | 633 | | |
564 | 634 | | |
565 | 635 | | |
566 | 636 | | |
567 | 637 | | |
568 | | - | |
| 638 | + | |
569 | 639 | | |
570 | 640 | | |
571 | 641 | | |
572 | 642 | | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
573 | 671 | | |
574 | 672 | | |
575 | 673 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
56 | | - | |
| 56 | + | |
57 | 57 | | |
58 | | - | |
| 58 | + | |
59 | 59 | | |
60 | | - | |
| 60 | + | |
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
| 66 | + | |
| 67 | + | |
66 | 68 | | |
67 | 69 | | |
68 | 70 | | |
| |||
0 commit comments