feat(react): React introspection, Web Vitals, and SPA primitives (#1257)

* feat(react): first-class React introspection, Web Vitals, and nextjs skill

Add React-general and web-universal features as first-class agent-browser verbs
(react tree/inspect/renders/suspense, vitals, pushstate). Genuinely Next.js-specific
workflows (PPR cookie protocol, /_next/mcp bridge, dev-server endpoints) ship as
a new `nextjs` skill that composes the primitives. No new runtime dependencies -
the React DevTools installHook.js is vendored (MIT) and include_str!'d into the
binary.

New commands:
  react tree                  Full React component tree (depth id parent name)
  react inspect <fiberId>     Props, hooks, state, source for one fiber
  react renders start|stop    Fiber profiler with Insts/Mounts/Re-renders/Self/DOM
                              + prev->next change details
  react suspense              Suspense boundaries + classifier (client-hook,
                              request-api, server-fetch, cache, stream, framework)
                              + root-cause grouping + recommendations
  vitals [url]                LCP/CLS/TTFB/FCP/INP + React hydration phases
  pushstate <url>             Generic SPA client-side navigation
  removeinitscript <id>       Remove a script registered via addinitscript

New launch flags:
  --init-script <path>        Register init scripts before first navigation
                              (repeatable; env AGENT_BROWSER_INIT_SCRIPTS)
  --enable <feature>          Built-in init scripts; currently react-devtools
                              (repeatable; env AGENT_BROWSER_ENABLE)

Other primitives:
  network route ... --resource-type <csv>  Filter by CDP resource type
  cookies set --curl <file>                Auto-detects JSON/cURL/Cookie-header

* fixes

* fixes

* fixes
This commit is contained in:
Chris Tate
2026-04-20 16:12:47 -05:00
committed by GitHub
parent cff12598bf
commit 57405f9361
22 changed files with 3438 additions and 18 deletions
+8
View File
@@ -389,6 +389,8 @@ pub struct DaemonOptions<'a> {
pub debug: bool,
pub executable_path: Option<&'a str>,
pub extensions: &'a [String],
pub init_scripts: &'a [String],
pub enable: &'a [String],
pub args: Option<&'a str>,
pub user_agent: Option<&'a str>,
pub proxy: Option<&'a str>,
@@ -430,6 +432,12 @@ fn apply_daemon_env(cmd: &mut Command, session: &str, opts: &DaemonOptions) {
if !opts.extensions.is_empty() {
cmd.env("AGENT_BROWSER_EXTENSIONS", opts.extensions.join(","));
}
if !opts.init_scripts.is_empty() {
cmd.env("AGENT_BROWSER_INIT_SCRIPTS", opts.init_scripts.join(","));
}
if !opts.enable.is_empty() {
cmd.env("AGENT_BROWSER_ENABLE", opts.enable.join(","));
}
if let Some(a) = opts.args {
cmd.env("AGENT_BROWSER_ARGS", a);
}