@agent-scope/runtime 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/console-interceptor.ts","../src/devtools-hook.ts","../src/error-detector.ts","../src/context-extractor.ts","../src/hooks-extractor.ts","../src/profiler.ts","../src/fiber-walker.ts","../src/suspense-detector.ts","../src/capture.ts","../src/index.ts"],"names":["serialize","_installed","ClassComponent","SuspenseComponent","HostText"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * console-interceptor.ts\n *\n * Monkey-patches `console.log`, `console.warn`, `console.error`,\n * `console.info`, `console.debug`, `console.group`, `console.groupCollapsed`,\n * `console.table`, and `console.trace` to capture messages with React\n * component attribution.\n *\n * Component attribution is resolved by reading the DevTools hook's\n * currently-active fiber (set during React render). When no fiber is active\n * (effect, event handler, async callback) `componentName` is `null`.\n *\n * The interceptor never suppresses output — every patched method calls the\n * original implementation with all original arguments.\n */\n\nimport type { ConsoleEntry, ConsoleLevel } from \"@agent-scope/core\";\nimport { serialize } from \"@agent-scope/core\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** All console levels we intercept. */\nconst INTERCEPTED_LEVELS: ConsoleLevel[] = [\n \"log\",\n \"warn\",\n \"error\",\n \"info\",\n \"debug\",\n \"group\",\n \"groupCollapsed\",\n \"table\",\n \"trace\",\n];\n\n// ---------------------------------------------------------------------------\n// Internal state\n// ---------------------------------------------------------------------------\n\n/** Captured entries since last `clearConsoleEntries()`. */\nconst _entries: ConsoleEntry[] = [];\n\n/** Original console methods saved at `install()` time. */\nconst _originals: Partial<Record<ConsoleLevel, (...args: unknown[]) => void>> = {};\n\n/** Whether the interceptor is currently installed. */\nlet _installed = false;\n\n// ---------------------------------------------------------------------------\n// Component attribution\n// ---------------------------------------------------------------------------\n\n/**\n * Attempt to discover the currently-rendering component name by inspecting\n * the React DevTools global hook.\n *\n * React sets `__REACT_DEVTOOLS_GLOBAL_HOOK__._currentFiber` (or an equivalent\n * field) to the active fiber during synchronous render work. This is the\n * same mechanism used by the React DevTools extension.\n *\n * Returns `null` when:\n * - No hook is installed\n * - No fiber is currently active (we're outside a render)\n */\nfunction getCurrentComponentName(): string | null {\n try {\n // Access the global hook\n const win =\n typeof window !== \"undefined\"\n ? window\n : typeof globalThis !== \"undefined\"\n ? globalThis\n : null;\n if (!win) return null;\n\n // biome-ignore lint/suspicious/noExplicitAny: accessing undocumented React internals\n const hook = (win as any).__REACT_DEVTOOLS_GLOBAL_HOOK__;\n if (!hook || typeof hook !== \"object\") return null;\n\n // React 18+ stores the current fiber in `_currentFiber` during render.\n // biome-ignore lint/suspicious/noExplicitAny: undocumented React internals\n const fiber: any = hook._currentFiber ?? hook.currentFiber ?? null;\n if (!fiber) return null;\n\n return extractFiberName(fiber);\n } catch {\n return null;\n }\n}\n\n/**\n * Extract a human-readable component name from a React fiber object.\n * Mirrors the logic in `fiber-walker.ts#extractName`.\n */\n// biome-ignore lint/suspicious/noExplicitAny: opaque fiber\nfunction extractFiberName(fiber: any): string | null {\n if (!fiber) return null;\n\n const { type } = fiber;\n if (!type) return null;\n\n // Function component or class component\n if (typeof type === \"function\") {\n return type.displayName || type.name || null;\n }\n\n // Forwarded refs: { $$typeof, render }\n if (typeof type === \"object\" && type !== null) {\n if (typeof type.displayName === \"string\" && type.displayName) {\n return type.displayName;\n }\n if (typeof type.render === \"function\") {\n return type.render.displayName || type.render.name || null;\n }\n // React.memo wraps: { $$typeof, type }\n if (type.type) {\n return extractFiberName({ type: type.type });\n }\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Preview builder\n// ---------------------------------------------------------------------------\n\n/**\n * Build a condensed single-line text preview from raw console arguments.\n *\n * Concatenates string representations of each argument, separated by spaces,\n * trimmed to 200 characters.\n */\nfunction buildPreview(args: unknown[]): string {\n const MAX = 200;\n const parts = args.map((arg) => {\n if (arg === null) return \"null\";\n if (arg === undefined) return \"undefined\";\n if (typeof arg === \"string\") return arg;\n if (typeof arg === \"number\" || typeof arg === \"boolean\" || typeof arg === \"bigint\") {\n return String(arg);\n }\n try {\n return JSON.stringify(arg);\n } catch {\n return String(arg);\n }\n });\n\n const joined = parts.join(\" \");\n return joined.length > MAX ? `${joined.slice(0, MAX - 1)}…` : joined;\n}\n\n// ---------------------------------------------------------------------------\n// Core interceptor factory\n// ---------------------------------------------------------------------------\n\nfunction makeWrapper(\n level: ConsoleLevel,\n original: (...args: unknown[]) => void,\n): (...args: unknown[]) => void {\n return function scopeConsoleWrapper(...args: unknown[]): void {\n // Always call through first so the console output is never suppressed\n original.apply(console, args);\n\n try {\n const componentName = getCurrentComponentName();\n const timestamp = Date.now();\n const serializedArgs = args.map((a) => serialize(a));\n const preview = buildPreview(args);\n\n const entry: ConsoleEntry = {\n level,\n args: serializedArgs,\n componentName,\n timestamp,\n preview,\n };\n\n _entries.push(entry);\n } catch {\n // Never let interceptor errors propagate — capture is best-effort\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Install the console interceptor.\n *\n * Replaces `console.log`, `console.warn`, `console.error`, `console.info`,\n * `console.debug`, `console.group`, `console.groupCollapsed`, `console.table`,\n * and `console.trace` with wrappers that record entries.\n *\n * Idempotent — calling `install` twice without `uninstall` in between is safe.\n */\nexport function installConsoleInterceptor(): void {\n if (_installed) return;\n _installed = true;\n\n for (const level of INTERCEPTED_LEVELS) {\n const original = console[level] as (...args: unknown[]) => void;\n _originals[level] = original;\n // biome-ignore lint/suspicious/noExplicitAny: intentional monkey-patch\n (console as any)[level] = makeWrapper(level, original);\n }\n}\n\n/**\n * Uninstall the console interceptor and restore all original methods.\n *\n * Idempotent — safe to call even if the interceptor is not installed.\n */\nexport function uninstallConsoleInterceptor(): void {\n if (!_installed) return;\n _installed = false;\n\n for (const level of INTERCEPTED_LEVELS) {\n const original = _originals[level];\n if (original !== undefined) {\n // biome-ignore lint/suspicious/noExplicitAny: restoring monkey-patch\n (console as any)[level] = original;\n }\n delete _originals[level];\n }\n}\n\n/**\n * Return a snapshot of all captured `ConsoleEntry` objects since the last\n * `clearConsoleEntries()` call (or since install).\n *\n * The returned array is a shallow copy — mutations do not affect the buffer.\n */\nexport function getConsoleEntries(): ConsoleEntry[] {\n return _entries.slice();\n}\n\n/**\n * Clear the captured entries buffer.\n */\nexport function clearConsoleEntries(): void {\n _entries.splice(0);\n}\n\n// ---------------------------------------------------------------------------\n// Internal reset helper (test only)\n// ---------------------------------------------------------------------------\n\n/**\n * @internal\n * Reset all module-level state. Used in unit tests to get a clean slate.\n */\nexport function _resetForTesting(): void {\n if (_installed) {\n uninstallConsoleInterceptor();\n }\n clearConsoleEntries();\n}\n","/**\n * devtools-hook.ts\n *\n * Installs and manages the React DevTools global hook\n * (`window.__REACT_DEVTOOLS_GLOBAL_HOOK__`).\n *\n * React checks for this hook at module initialisation time, so it MUST be\n * installed before any React bundle is evaluated. Call `installHook()` as\n * early as possible (e.g. the very first script on the page).\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal shape of a React renderer as surfaced through the DevTools hook.\n *\n * React passes a much larger object; we only reference the fields we need.\n */\nexport interface ReactRenderer {\n /** Opaque renderer ID assigned by the hook on injection. */\n id: number;\n /** The renderer object passed by React via `inject()`. */\n // biome-ignore lint/suspicious/noExplicitAny: opaque React internals\n renderer: any;\n /** Set of fiber root containers managed by this renderer. */\n // biome-ignore lint/suspicious/noExplicitAny: opaque React internals\n fiberRoots: Set<any>;\n}\n\n/**\n * The shape we install at `window.__REACT_DEVTOOLS_GLOBAL_HOOK__`.\n *\n * React calls `inject(renderer)` when it boots, giving us access to its\n * internal fiber roots. Everything else is just enough scaffolding to keep\n * React happy.\n */\nexport interface ScopeDevToolsHook {\n /** Required by React – signals that DevTools are present. */\n isDisabled: false;\n /** Required by React – signals DevTools support for profiling. */\n supportsFiber: true;\n /**\n * Called by React when it initialises a new renderer instance.\n * Returns the renderer's numeric ID.\n */\n inject(renderer: unknown): number;\n /** Called by React before each commit (we no-op this). */\n onCommitFiberRoot(rendererID: number, root: unknown, priorityLevel: unknown): void;\n /** Called by React when an unmount occurs (we no-op this). */\n onCommitFiberUnmount(rendererID: number, fiber: unknown): void;\n /** Called by React before post-commit effects (we no-op this). */\n onPostCommitFiberRoot(rendererID: number, root: unknown): void;\n /** Extension point: registered renderers keyed by ID. */\n _renderers: Map<number, ReactRenderer>;\n /** Whether the hook was installed by Scope (vs. pre-existing DevTools). */\n _isScopeHook: true;\n}\n\n// ---------------------------------------------------------------------------\n// Internal state\n// ---------------------------------------------------------------------------\n\n/**\n * The installed hook instance (null until `installHook()` is called or a\n * pre-existing hook is found).\n */\nlet _hook: ScopeDevToolsHook | null = null;\n\n/** Auto-incrementing renderer ID counter. */\nlet _nextRendererID = 1;\n\n/** Listeners waiting for the first renderer registration. */\nconst _rendererListeners: Array<(renderer: ReactRenderer) => void> = [];\n\n// ---------------------------------------------------------------------------\n// Hook factory\n// ---------------------------------------------------------------------------\n\nfunction createScopeHook(): ScopeDevToolsHook {\n const renderers = new Map<number, ReactRenderer>();\n\n const hook: ScopeDevToolsHook = {\n isDisabled: false,\n supportsFiber: true,\n _renderers: renderers,\n _isScopeHook: true,\n\n inject(renderer: unknown): number {\n const id = _nextRendererID++;\n const entry: ReactRenderer = {\n id,\n renderer,\n // biome-ignore lint/suspicious/noExplicitAny: React renderer internals\n fiberRoots: new Set<any>(),\n };\n renderers.set(id, entry);\n\n // Notify any waiting listeners\n for (const listener of _rendererListeners.splice(0)) {\n listener(entry);\n }\n\n return id;\n },\n\n onCommitFiberRoot(rendererID: number, root: unknown, _priorityLevel: unknown): void {\n const entry = renderers.get(rendererID);\n if (entry) {\n entry.fiberRoots.add(root);\n }\n },\n\n onCommitFiberUnmount(_rendererID: number, _fiber: unknown): void {\n // no-op — we don't track individual unmounts\n },\n\n onPostCommitFiberRoot(_rendererID: number, _root: unknown): void {\n // no-op\n },\n };\n\n return hook;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Install the Scope DevTools hook at `window.__REACT_DEVTOOLS_GLOBAL_HOOK__`.\n *\n * - If no hook exists yet, installs a new Scope hook.\n * - If a Scope hook is already installed, returns the existing instance.\n * - If a *third-party* hook is already present (e.g. real React DevTools),\n * we patch it minimally so that renderer registrations are forwarded to us\n * as well.\n *\n * Must be called **before React is loaded** to intercept `inject()`.\n */\nexport function installHook(): ScopeDevToolsHook {\n if (_hook !== null) {\n return _hook;\n }\n\n // Safe check for browser globals\n const win =\n typeof window !== \"undefined\"\n ? (window as Window &\n typeof globalThis & {\n __REACT_DEVTOOLS_GLOBAL_HOOK__?: unknown;\n })\n : null;\n\n if (win === null) {\n // Non-browser environment (Node test, SSR) — create a detached hook\n _hook = createScopeHook();\n return _hook;\n }\n\n const existing = win.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n\n if (existing && typeof existing === \"object\") {\n const existingHook = existing as Record<string, unknown>;\n\n // Already our hook\n if (existingHook._isScopeHook === true) {\n _hook = existing as ScopeDevToolsHook;\n return _hook;\n }\n\n // A third-party hook (real DevTools) exists — patch inject() to also\n // forward to our renderer registry.\n const scopeHook = createScopeHook();\n const originalInject = existingHook.inject as ((renderer: unknown) => number) | undefined;\n\n existingHook.inject = (renderer: unknown): number => {\n const originalId =\n typeof originalInject === \"function\" ? originalInject.call(existing, renderer) : -1;\n scopeHook.inject(renderer);\n return originalId;\n };\n\n // Keep _renderers accessible from the patched hook\n existingHook._renderers = scopeHook._renderers;\n existingHook._isScopeHook = true;\n\n _hook = scopeHook;\n return _hook;\n }\n\n // No existing hook — install ours\n _hook = createScopeHook();\n win.__REACT_DEVTOOLS_GLOBAL_HOOK__ = _hook;\n return _hook;\n}\n\n/**\n * Retrieve the currently installed hook.\n *\n * Returns `null` if `installHook()` has not yet been called.\n */\nexport function getHook(): ScopeDevToolsHook | null {\n return _hook;\n}\n\n/**\n * Return a snapshot of all registered React renderers.\n *\n * Empty until React calls `inject()`.\n */\nexport function getRenderers(): ReactRenderer[] {\n if (_hook === null) return [];\n return Array.from(_hook._renderers.values());\n}\n\n/**\n * Wait until at least one React renderer has registered with the hook.\n *\n * @param timeout - Maximum milliseconds to wait (default: 10 000).\n * @returns A promise that resolves with the first registered renderer.\n * @throws If the timeout elapses with no renderer.\n */\nexport function waitForReact(timeout = 10_000): Promise<ReactRenderer> {\n // Install if not already done\n const hook = _hook ?? installHook();\n\n // If a renderer is already registered, resolve immediately\n const existing = Array.from(hook._renderers.values());\n if (existing.length > 0) {\n return Promise.resolve(existing[0] as ReactRenderer);\n }\n\n return new Promise<ReactRenderer>((resolve, reject) => {\n const timer = setTimeout(() => {\n const idx = _rendererListeners.indexOf(listener);\n if (idx !== -1) _rendererListeners.splice(idx, 1);\n reject(new Error(`waitForReact: timed out after ${timeout}ms`));\n }, timeout);\n\n const listener = (renderer: ReactRenderer): void => {\n clearTimeout(timer);\n resolve(renderer);\n };\n\n _rendererListeners.push(listener);\n });\n}\n\n// ---------------------------------------------------------------------------\n// Internal reset helper (test only)\n// ---------------------------------------------------------------------------\n\n/**\n * @internal\n * Reset all module-level state. Used in unit tests to get a clean slate.\n */\nexport function _resetForTesting(): void {\n _hook = null;\n _nextRendererID = 1;\n _rendererListeners.splice(0);\n}\n","/**\n * error-detector.ts\n *\n * Detects React error boundaries in the fiber tree and extracts information\n * about any errors they have caught.\n *\n * React error boundaries are class components that implement at least one of:\n * - `static getDerivedStateFromError(error)` — static method\n * - `componentDidCatch(error, info)` — instance method\n *\n * When a boundary has caught an error, React stores error info in the fiber's\n * `memoizedState` (the current component state snapshot). Common patterns:\n * - `{ hasError: true, error: Error }` (class-level state)\n * - `{ error: Error }` (minimal pattern)\n *\n * We walk the fiber tree, identify boundary components, inspect their state,\n * and build `CapturedError` objects when an error is present.\n */\n\nimport type { CapturedError } from \"@agent-scope/core\";\nimport type { Fiber } from \"./fiber-walker.js\";\n\n// ---------------------------------------------------------------------------\n// Fiber tag constants\n// ---------------------------------------------------------------------------\n\nconst ClassComponent = 1;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extract a display name from a fiber — mirrors the logic in fiber-walker.ts\n * but kept local to avoid a circular dependency.\n */\nfunction fiberName(fiber: Fiber): string {\n const { type } = fiber;\n if (!type) return \"Anonymous\";\n if (typeof type === \"string\") return type;\n if (typeof type.displayName === \"string\" && type.displayName) return type.displayName;\n if (typeof type.name === \"string\" && type.name) return type.name;\n return \"Anonymous\";\n}\n\n/**\n * Return `true` when the class constructor indicates this fiber is an error\n * boundary.\n *\n * A component is an error boundary when it defines:\n * 1. `static getDerivedStateFromError` — checked on the class (type)\n * 2. `componentDidCatch` — checked on the prototype (instance method)\n */\nfunction isErrorBoundary(fiber: Fiber): boolean {\n if (fiber.tag !== ClassComponent) return false;\n const type = fiber.type;\n if (!type || typeof type !== \"function\") return false;\n\n // Static method (React 16.3+)\n if (typeof type.getDerivedStateFromError === \"function\") return true;\n\n // Instance method via prototype\n if (type.prototype && typeof type.prototype.componentDidCatch === \"function\") return true;\n\n return false;\n}\n\n/**\n * Try to extract an `Error` instance (or error-like object) from the\n * boundary's current memoized state.\n *\n * React itself does not mandate a particular state shape for error boundaries\n * — it's up to the component author. We look for the most common patterns:\n *\n * 1. `state.error instanceof Error` (most common)\n * 2. `state.hasError === true && state.error` (two-field pattern)\n * 3. `state` itself is an `Error` (rare but valid)\n */\n// biome-ignore lint/suspicious/noExplicitAny: React fiber state is untyped\nfunction extractErrorFromState(memoizedState: any): Error | null {\n if (memoizedState === null || memoizedState === undefined) return null;\n\n // Direct Error instance stored in state\n if (memoizedState instanceof Error) return memoizedState;\n\n if (typeof memoizedState !== \"object\") return null;\n\n // Standard two-field pattern: { hasError: true, error: Error }\n if (memoizedState.hasError === true && memoizedState.error instanceof Error) {\n return memoizedState.error;\n }\n\n // Simple one-field pattern: { error: Error }\n if (memoizedState.error instanceof Error) return memoizedState.error;\n\n // Some components store the error under a different key; check any value\n // that is an Error instance\n for (const key of Object.keys(memoizedState)) {\n if (memoizedState[key] instanceof Error) return memoizedState[key];\n }\n\n return null;\n}\n\n/**\n * Walk the fiber tree upward from `fiber` to find the nearest ancestor that\n * is an error boundary. Returns `null` if none is found.\n */\nfunction findNearestBoundaryName(fiber: Fiber): string | null {\n let current: Fiber | null = fiber.return ?? null;\n while (current !== null) {\n if (isErrorBoundary(current)) {\n return fiberName(current);\n }\n current = current.return ?? null;\n }\n return null;\n}\n\n/**\n * Walk the fiber tree depth-first and collect `CapturedError` entries for\n * every error boundary that is currently holding a caught error.\n *\n * @param rootFiber - Top of the fiber tree (typically `HostRoot.child`).\n * @returns Array of `CapturedError` objects; empty when nothing has been caught.\n */\nexport function detectErrors(rootFiber: Fiber | null): CapturedError[] {\n const results: CapturedError[] = [];\n const visited = new Set<Fiber>();\n\n function walk(fiber: Fiber | null): void {\n if (fiber === null || fiber === undefined) return;\n if (visited.has(fiber)) return;\n visited.add(fiber);\n\n if (isErrorBoundary(fiber)) {\n const error = extractErrorFromState(fiber.memoizedState);\n if (error !== null) {\n // The boundary itself caught the error; the throwing component is\n // typically the child that is now unmounted. We attribute it to the\n // first child of the boundary when available, otherwise to the\n // boundary component itself.\n const throwingChild = fiber.child;\n const componentName = throwingChild ? fiberName(throwingChild) : fiberName(fiber);\n const boundaryName = fiberName(fiber);\n\n // Walk upward to check for an enclosing boundary (nested boundaries)\n const enclosingBoundary = findNearestBoundaryName(fiber);\n\n results.push({\n message: error.message ?? String(error),\n name: error.name ?? \"Error\",\n stack: error.stack ?? null,\n source: null, // Stack parsing is left to consumers\n componentName,\n timestamp: Date.now(),\n capturedBy: \"boundary\",\n // Store boundary name as a non-standard extension that typed consumers\n // can access. The interface only requires the defined fields.\n ...({ boundaryName: enclosingBoundary ?? boundaryName } as Partial<CapturedError>),\n });\n }\n }\n\n walk(fiber.child ?? null);\n walk(fiber.sibling ?? null);\n }\n\n walk(rootFiber);\n return results;\n}\n","/**\n * context-extractor.ts\n *\n * Detects React context consumers and providers in a fiber tree and extracts\n * their consumed / provided values.\n *\n * React context internals we rely on:\n * - `fiber.dependencies` — linked list of context dependencies (React ≥17)\n * - `fiber.contextDependencies` — same, older React 16 name\n * - `dependency.context` — the React context object\n * - `context._currentValue` — the current provided value (primary context slot)\n * - `context.displayName` — optional human-readable name\n * - `fiber.tag === 10` — ContextProvider fiber\n * - `fiber.type._context` — context object on a provider fiber\n * - `fiber.memoizedProps.value` — value prop of a Provider\n *\n * None of these fields are part of React's public API; they are undocumented\n * implementation details that may change across React versions.\n */\n\nimport type { ContextConsumption, SerializedValue } from \"@agent-scope/core\";\nimport { serialize } from \"@agent-scope/core\";\nimport type { Fiber } from \"./fiber-walker.js\";\n\n// ---------------------------------------------------------------------------\n// Internal constants\n// ---------------------------------------------------------------------------\n\n/** Fiber tag for ContextProvider (React source: ReactWorkTags.js). */\nconst CONTEXT_PROVIDER_TAG = 10;\n\n/** Fiber tag for ContextConsumer (React source: ReactWorkTags.js). */\nconst CONTEXT_CONSUMER_TAG = 9;\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a human-readable name for a React context object.\n *\n * Resolution order:\n * 1. `context.displayName` — explicitly set by the application\n * 2. Constructor name of `_currentValue` — unreliable but a useful hint\n * 3. `null` — no name available\n */\nfunction resolveContextName(\n // biome-ignore lint/suspicious/noExplicitAny: React context internals\n context: any,\n): string | null {\n if (!context || typeof context !== \"object\") return null;\n\n if (typeof context.displayName === \"string\" && context.displayName) {\n return context.displayName;\n }\n\n // Constructor name heuristic — skip generic built-in names\n const currentValue = context._currentValue;\n if (currentValue !== null && currentValue !== undefined && typeof currentValue === \"object\") {\n const ctorName: unknown = currentValue.constructor?.name;\n if (typeof ctorName === \"string\" && ctorName && ctorName !== \"Object\" && ctorName !== \"Array\") {\n return ctorName;\n }\n }\n\n return null;\n}\n\n/**\n * Read the linked list of context dependencies off a fiber.\n *\n * React ≥17 stores them on `fiber.dependencies.firstContext`; React 16 used\n * `fiber.contextDependencies.first`. We try both locations defensively.\n *\n * Returns an empty array when no context dependencies are found.\n */\n// biome-ignore lint/suspicious/noExplicitAny: React fiber internals\nfunction readContextDependencies(fiber: Fiber): any[] {\n // React 17+\n // biome-ignore lint/suspicious/noExplicitAny: fiber internals\n const first: any =\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n (fiber as any).dependencies?.firstContext ??\n // React 16 legacy field\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n (fiber as any).contextDependencies?.first ??\n null;\n\n if (first === null || first === undefined) return [];\n\n const deps: unknown[] = [];\n let node = first;\n while (node !== null && node !== undefined) {\n deps.push(node);\n node = node.next ?? null;\n }\n return deps;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Extract all React context consumptions from a fiber.\n *\n * Reads the fiber's context dependency linked list and returns a\n * `ContextConsumption` for every context the component reads. If the fiber\n * has no context dependencies an empty array is returned.\n *\n * @param fiber - The fiber to inspect.\n * @returns An array of context consumptions (may be empty).\n */\nexport function extractContextConsumptions(fiber: Fiber): ContextConsumption[] {\n // ContextConsumer fibers (tag 9) hold their context on `fiber.type`\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n if ((fiber as any).tag === CONTEXT_CONSUMER_TAG) {\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n const context = (fiber as any).type;\n if (context && typeof context === \"object\") {\n const contextName = resolveContextName(context);\n const raw: unknown = context._currentValue;\n return [\n {\n contextName,\n value: serialize(raw as Record<string, unknown>),\n didTriggerRender: false,\n },\n ];\n }\n return [];\n }\n\n const deps = readContextDependencies(fiber);\n if (deps.length === 0) return [];\n\n const consumptions: ContextConsumption[] = [];\n\n for (const dep of deps) {\n const context = dep.context ?? dep.observedBits /* React 16 */ ?? null;\n if (!context || typeof context !== \"object\") continue;\n\n // The current value lives on _currentValue (primary slot).\n // React maintains two slots (_currentValue / _currentValue2) for\n // concurrent mode; we only read the primary slot.\n const raw: unknown = context._currentValue;\n const contextName = resolveContextName(context);\n\n consumptions.push({\n contextName,\n value: serialize(raw as Record<string, unknown>),\n didTriggerRender: false,\n });\n }\n\n return consumptions;\n}\n\n/**\n * Extract context provider information from a ContextProvider fiber (tag 10).\n *\n * For non-provider fibers this returns an empty array.\n *\n * @param fiber - The fiber to inspect.\n * @returns An array with a single entry for a provider fiber, or empty array.\n */\nexport function extractContextProviders(\n fiber: Fiber,\n): Array<{ contextName: string | null; value: SerializedValue }> {\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n if ((fiber as any).tag !== CONTEXT_PROVIDER_TAG) return [];\n\n // The context object lives at fiber.type._context on a Provider fiber.\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n const context = (fiber as any).type?._context ?? null;\n\n // The provided value is the `value` prop.\n // biome-ignore lint/suspicious/noExplicitAny: React fiber memoizedProps\n const raw: unknown = (fiber.memoizedProps as any)?.value;\n\n const contextName = context ? resolveContextName(context) : null;\n\n return [\n {\n contextName,\n value: serialize(raw as Record<string, unknown>),\n },\n ];\n}\n","/**\n * hooks-extractor.ts\n *\n * Extracts `HookState[]` from a React fiber's `memoizedState` linked list.\n *\n * React stores hooks as a singly-linked list where each node has:\n * - `memoizedState` — the hook's stored value (shape varies by hook type)\n * - `queue` — update queue present on useState / useReducer\n * - `next` — pointer to the next hook node in call order\n *\n * Hook types are NOT tagged by React, so we identify them by inspecting the\n * shape of each node (duck-typing). The heuristics below mirror the internal\n * structure documented in React's source (ReactFiberHooks.js).\n *\n * @internal\n */\n\nimport type { HookState, HookType } from \"@agent-scope/core\";\nimport { serialize } from \"@agent-scope/core\";\n\n// ---------------------------------------------------------------------------\n// React internal constants (ReactHookEffectTags.js)\n// ---------------------------------------------------------------------------\n\n/** Layout effect flag — set on `useLayoutEffect` hooks. */\nconst HookLayout = 0b00100; // 4\n\n// ---------------------------------------------------------------------------\n// Internal hook-node shape\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal structural shape of a React hook linked-list node.\n *\n * React's actual internal type is much larger; we only read the fields\n * relevant to hook extraction.\n */\ninterface HookNode {\n memoizedState: unknown;\n // biome-ignore lint/suspicious/noExplicitAny: React update queue internals\n queue: Record<string, any> | null | undefined;\n next: HookNode | null;\n}\n\n/**\n * Shape of a React effect object (the value stored in `memoizedState` for\n * `useEffect` and `useLayoutEffect` hooks).\n */\ninterface EffectObject {\n tag: number;\n create: () => unknown;\n destroy: (() => void) | null | undefined;\n deps: unknown[] | null;\n // biome-ignore lint/suspicious/noExplicitAny: React effect circular list\n next: any;\n}\n\n// ---------------------------------------------------------------------------\n// Type identification helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Return true when `node.memoizedState` looks like a React effect object.\n *\n * Effect nodes store the full effect descriptor AS their memoizedState.\n * Distinguishing traits: `create` is a function and a `deps` key exists.\n */\nfunction isEffectNode(node: HookNode): node is HookNode & { memoizedState: EffectObject } {\n const ms = node.memoizedState;\n if (ms === null || typeof ms !== \"object\") return false;\n const obj = ms as Record<string, unknown>;\n return typeof obj.create === \"function\" && \"deps\" in obj && typeof obj.tag === \"number\";\n}\n\n/**\n * Return true when `node.memoizedState` looks like a `useRef` ref object.\n *\n * React stores ref objects as `{ current: value }`. We confirm there is no\n * `queue` (which would indicate useState/useReducer instead).\n */\nfunction isRefNode(node: HookNode): boolean {\n if (node.queue != null) return false;\n const ms = node.memoizedState;\n if (ms === null || typeof ms !== \"object\" || Array.isArray(ms)) return false;\n const keys = Object.keys(ms as object);\n return keys.length === 1 && keys[0] === \"current\";\n}\n\n/**\n * Return true when `node.memoizedState` is a `[value, deps]` tuple used by\n * `useMemo` and `useCallback`.\n */\nfunction isMemoTuple(node: HookNode): boolean {\n if (node.queue != null) return false;\n const ms = node.memoizedState;\n if (!Array.isArray(ms) || ms.length !== 2) return false;\n // deps must be an array or null — if it's neither, likely not a memo tuple\n return ms[1] === null || Array.isArray(ms[1]);\n}\n\n/**\n * Return true when the node has an update queue with a `dispatch` function,\n * indicating a `useState` or `useReducer` hook.\n */\nfunction isStateOrReducerNode(node: HookNode): boolean {\n return (\n node.queue != null &&\n typeof node.queue === \"object\" &&\n typeof node.queue.dispatch === \"function\"\n );\n}\n\n/**\n * Distinguish `useReducer` from `useState` by inspecting the queue's\n * `lastRenderedReducer`.\n *\n * React's basic `useState` reducer is: `(state, action) => action` (a no-op\n * pass-through for the action). `useReducer` supplies a real reducer function\n * with a different arity / body. We can't inspect the body, but we can look\n * at whether the renderer exposed a `reducer` property on the queue or if the\n * name of `lastRenderedReducer` matches the built-in patterns.\n */\nfunction isReducerNode(node: HookNode): boolean {\n if (!isStateOrReducerNode(node)) return false;\n const q = node.queue as Record<string, unknown>;\n\n // If the queue carries an explicit `reducer` property (some React builds), trust it.\n if (typeof q.reducer === \"function\") return true;\n\n const lrr = q.lastRenderedReducer;\n if (typeof lrr !== \"function\") return false;\n\n // React names its built-in useState reducer \"basicStateReducer\". Any\n // other name strongly implies a user-supplied reducer.\n const name = (lrr as { name?: string }).name ?? \"\";\n return name !== \"basicStateReducer\" && name !== \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Effect classification\n// ---------------------------------------------------------------------------\n\nfunction classifyEffectType(effect: EffectObject): \"useEffect\" | \"useLayoutEffect\" {\n if (effect.tag & HookLayout) return \"useLayoutEffect\";\n // passive flag (0b01000) or unknown tag → default to useEffect\n return \"useEffect\";\n}\n\n// ---------------------------------------------------------------------------\n// Dependency serialisation helper\n// ---------------------------------------------------------------------------\n\nfunction serializeDeps(deps: unknown[] | null | undefined): ReturnType<typeof serialize>[] | null {\n if (deps === null || deps === undefined) return null;\n if (!Array.isArray(deps)) return null;\n return deps.map((d) => serialize(d));\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Extract an ordered list of `HookState` snapshots from a fiber's\n * `memoizedState` linked list.\n *\n * @param fiber - A React fiber object (typed as `any` because React doesn't\n * export its internal fiber shape).\n * @returns An ordered array of `HookState` entries (one per hook call),\n * or an empty array if the fiber has no hooks or is null.\n */\n// biome-ignore lint/suspicious/noExplicitAny: React fiber internals\nexport function extractHooks(fiber: any): HookState[] {\n if (fiber == null) return [];\n\n // biome-ignore lint/suspicious/noExplicitAny: React hook node internals\n let node: HookNode | null = (fiber.memoizedState as any) ?? null;\n if (node === null) return [];\n\n const hooks: HookState[] = [];\n\n while (node !== null) {\n hooks.push(classifyNode(node));\n node = node.next ?? null;\n }\n\n return hooks;\n}\n\n// ---------------------------------------------------------------------------\n// Per-node classification\n// ---------------------------------------------------------------------------\n\nfunction classifyNode(node: HookNode): HookState {\n // ── Effect hooks (useEffect / useLayoutEffect) ─────────────────────────\n if (isEffectNode(node)) {\n const effect = node.memoizedState as EffectObject;\n const hookType = classifyEffectType(effect);\n return {\n type: hookType,\n name: null,\n value: serialize(undefined),\n deps: serializeDeps(effect.deps),\n hasCleanup: typeof effect.destroy === \"function\",\n };\n }\n\n // ── useRef ────────────────────────────────────────────────────────────\n if (isRefNode(node)) {\n const ref = node.memoizedState as { current: unknown };\n return {\n type: \"useRef\",\n name: null,\n value: serialize(ref.current),\n deps: null,\n hasCleanup: null,\n };\n }\n\n // ── useMemo / useCallback ─────────────────────────────────────────────\n if (isMemoTuple(node)) {\n const [val, deps] = node.memoizedState as [unknown, unknown[] | null];\n const hookType: HookType = typeof val === \"function\" ? \"useCallback\" : \"useMemo\";\n return {\n type: hookType,\n name: null,\n value: serialize(val),\n deps: serializeDeps(deps),\n hasCleanup: null,\n };\n }\n\n // ── useState / useReducer ─────────────────────────────────────────────\n if (isStateOrReducerNode(node)) {\n const hookType: HookType = isReducerNode(node) ? \"useReducer\" : \"useState\";\n return {\n type: hookType,\n name: null,\n value: serialize(node.memoizedState),\n deps: null,\n hasCleanup: null,\n };\n }\n\n // ── Fallback: custom / unrecognised ───────────────────────────────────\n return {\n type: \"custom\",\n name: null,\n value: serialize(node.memoizedState),\n deps: null,\n hasCleanup: null,\n };\n}\n","/**\n * profiler.ts\n *\n * Instruments React's commit cycle to capture per-component render timing data.\n *\n * React exposes profiling data on fiber objects in development/profiling builds:\n * - `fiber.actualDuration` — wall-clock ms spent rendering this fiber + descendants\n * - `fiber.selfBaseDuration` — ms spent rendering just this fiber (excl. children)\n * - `fiber.actualStartTime` — performance.now() timestamp when render began\n *\n * We hook into `onCommitFiberRoot` on the DevTools hook to intercept every\n * commit, walk the work-in-progress subtree, and accumulate counts + durations\n * keyed by fiber identity.\n */\n\nimport type { ScopeDevToolsHook } from \"./devtools-hook.js\";\nimport type { Fiber } from \"./fiber-walker.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Profiling record stored per fiber. */\ninterface ProfilingRecord {\n renderCount: number;\n renderDuration: number;\n}\n\n/** Public snapshot returned by `getProfilingData`. */\nexport interface ProfilingSnapshot {\n renderCount: number;\n renderDuration: number;\n}\n\n// ---------------------------------------------------------------------------\n// Internal state\n// ---------------------------------------------------------------------------\n\n/**\n * Map from fiber numeric ID → profiling record.\n *\n * We key by `fiber._debugID` when present, falling back to the object\n * reference itself stored in `_fiberRefMap`.\n */\nconst _profilingData = new Map<number, ProfilingRecord>();\n\n/**\n * Secondary map for fibers that lack `_debugID`.\n * Maps the fiber object → a synthetic numeric key so we still accumulate\n * data across commits for the same fiber.\n */\nconst _fiberRefMap = new WeakMap<object, number>();\n\n/** Counter for synthetic IDs assigned to fibers without `_debugID`. */\nlet _syntheticIdCounter = -1;\n\n/** Whether the profiler has been installed on a hook. */\nlet _installed = false;\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Derive a stable numeric key for a fiber.\n *\n * React assigns `_debugID` in development builds (>=16). In environments\n * where it's absent we mint a synthetic negative integer so it never collides\n * with React's positive IDs.\n */\nfunction fiberId(fiber: Fiber): number {\n if (typeof fiber._debugID === \"number\") {\n return fiber._debugID;\n }\n // Use the fiber object itself as a WeakMap key\n const existing = _fiberRefMap.get(fiber);\n if (existing !== undefined) return existing;\n const id = _syntheticIdCounter--;\n _fiberRefMap.set(fiber, id);\n return id;\n}\n\n/**\n * Walk an alternate (work-in-progress) fiber subtree and accumulate profiling\n * data for every node that has `actualDuration` set (i.e. was actually\n * rendered in this commit).\n *\n * React sets `actualDuration === -1` (or leaves it unset) for fibers that\n * were bailed out of rendering — we skip those.\n *\n * We walk via `child` + `sibling` rather than relying on the `return` pointer\n * so we stay within the committed subtree.\n */\nfunction walkCommittedFibers(fiber: Fiber | null): void {\n if (fiber === null || fiber === undefined) return;\n\n const actualDuration: number =\n typeof fiber.actualDuration === \"number\" ? fiber.actualDuration : -1;\n const selfBaseDuration: number =\n typeof fiber.selfBaseDuration === \"number\" ? fiber.selfBaseDuration : 0;\n\n // A non-negative actualDuration means this fiber was rendered in this commit\n if (actualDuration >= 0) {\n const id = fiberId(fiber);\n const existing = _profilingData.get(id);\n if (existing !== undefined) {\n existing.renderCount += 1;\n // Accumulate self (not total) duration so parent durations don't double-count\n existing.renderDuration += selfBaseDuration;\n } else {\n _profilingData.set(id, {\n renderCount: 1,\n renderDuration: selfBaseDuration,\n });\n }\n }\n\n // Recurse into children and siblings\n walkCommittedFibers(fiber.child ?? null);\n walkCommittedFibers(fiber.sibling ?? null);\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Install the profiler onto a DevTools hook.\n *\n * Wraps `hook.onCommitFiberRoot` so that every React commit triggers a walk\n * of the committed fiber subtree to accumulate profiling data.\n *\n * Safe to call multiple times — subsequent calls on the same hook are no-ops.\n */\nexport function installProfiler(hook: ScopeDevToolsHook): void {\n if (_installed) return;\n _installed = true;\n\n const originalOnCommit = hook.onCommitFiberRoot.bind(hook);\n\n hook.onCommitFiberRoot = (\n rendererID: number,\n // biome-ignore lint/suspicious/noExplicitAny: React DevTools hook signature\n root: any,\n priorityLevel: unknown,\n ): void => {\n // Call the original handler first so fiber roots are tracked\n originalOnCommit(rendererID, root, priorityLevel);\n\n // Walk the work-in-progress (alternate) fiber tree for profiling data.\n // `root.current` is the current committed tree; `root.current.alternate`\n // is the work-in-progress tree that was just committed.\n const wipRoot: Fiber | null = root?.current?.alternate ?? root?.current ?? null;\n if (wipRoot !== null) {\n walkCommittedFibers(wipRoot);\n }\n };\n}\n\n/**\n * Retrieve the accumulated profiling snapshot for a fiber by its numeric ID.\n *\n * @param fiberId - The fiber's `_debugID` (or synthetic ID assigned by this module).\n * @returns `{ renderCount, renderDuration }` if data exists, `null` otherwise.\n */\nexport function getProfilingData(fiberIdParam: number): ProfilingSnapshot | null {\n const record = _profilingData.get(fiberIdParam);\n if (record === undefined) return null;\n return { renderCount: record.renderCount, renderDuration: record.renderDuration };\n}\n\n/**\n * Reset all accumulated profiling data and the installed state.\n *\n * Primarily used in tests and when re-initialising the capture session.\n * Note: this does NOT restore the original `onCommitFiberRoot` handler —\n * call `installProfiler` again on a fresh hook after resetting.\n */\nexport function resetProfilingData(): void {\n _profilingData.clear();\n _installed = false;\n _syntheticIdCounter = -1;\n // WeakMap entries are GC'd automatically; no need to clear _fiberRefMap\n}\n\n/**\n * @internal\n * Expose the raw data map for testing purposes.\n */\nexport function _getProfilingDataMap(): Map<number, ProfilingRecord> {\n return _profilingData;\n}\n","/**\n * fiber-walker.ts\n *\n * Traverses a React fiber tree and converts it into the `ComponentNode` tree\n * defined in `@agent-scope/core`.\n *\n * Fiber internals are undocumented React implementation details. We rely on:\n * - `fiber.tag` — type classifier (see FIBER_TAGS below)\n * - `fiber.type` — function/class reference or string for host elements\n * - `fiber.memoizedProps` — current props snapshot\n * - `fiber.child` — first child fiber\n * - `fiber.sibling` — next sibling fiber\n * - `fiber._debugSource` — source location injected by babel (dev only)\n * - `fiber._debugID` — internal numeric ID (dev only, may be absent)\n * - `fiber.index` — position among siblings\n */\n\nimport type { ComponentNode, ComponentType, SourceLocation } from \"@agent-scope/core\";\nimport { serialize } from \"@agent-scope/core\";\nimport { extractContextConsumptions } from \"./context-extractor.js\";\nimport { extractHooks } from \"./hooks-extractor.js\";\nimport { getProfilingData } from \"./profiler.js\";\n\n// ---------------------------------------------------------------------------\n// Fiber tag constants (React source: ReactWorkTags.js)\n// ---------------------------------------------------------------------------\n\nconst FunctionComponent = 0;\nconst ClassComponent = 1;\nconst IndeterminateComponent = 2;\nconst HostRoot = 3;\n// HostPortal = 4 (not used for node extraction)\nconst HostComponent = 5;\nconst HostText = 6;\nconst Fragment = 7;\n// Mode = 8 (StrictMode etc.)\n// ContextConsumer = 9\n// ContextProvider = 10\nconst ForwardRef = 11;\n// Profiler = 12\nconst SuspenseComponent = 13;\nconst MemoComponent = 14;\nconst SimpleMemoComponent = 15;\n// LazyComponent = 16\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal shape of a React fiber as accessed by this walker.\n * Only the fields we actually read are declared here.\n */\nexport interface Fiber {\n tag: number;\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n type: any;\n // biome-ignore lint/suspicious/noExplicitAny: arbitrary props\n memoizedProps: Record<string, any> | null;\n child: Fiber | null;\n sibling: Fiber | null;\n return: Fiber | null;\n /** Present in React dev builds (>=16). Numeric per-session fiber ID. */\n _debugID?: number;\n /** Position among siblings (0-based). Used as fallback ID. */\n index: number;\n /** Injected by `babel-plugin-transform-react-jsx-source` (dev only). */\n _debugSource?: {\n fileName: string;\n lineNumber: number;\n columnNumber: number;\n } | null;\n // biome-ignore lint/suspicious/noExplicitAny: arbitrary\n [key: string]: any;\n}\n\nexport interface WalkOptions {\n /**\n * When `true`, host elements (div, span, etc.) are included in the output.\n * Default: `false`.\n */\n includeHostElements?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Sequential ID generator\n// ---------------------------------------------------------------------------\n\nlet _idCounter = 1;\n\n/** Reset the ID counter. Used in unit tests only. */\nexport function _resetIdCounter(): void {\n _idCounter = 1;\n}\n\nfunction nextId(): number {\n return _idCounter++;\n}\n\n// ---------------------------------------------------------------------------\n// Name extraction helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Property key names that JS engines infer automatically from object\n * literals, which we must NOT treat as user-supplied display names.\n *\n * e.g. `{ render: () => null }.render.name === \"render\"` due to inferred names.\n */\nconst INFERRED_PROPERTY_NAMES = new Set([\"render\", \"type\", \"forward_ref\", \"memo\"]);\n\nfunction isUserSuppliedName(name: unknown, tag: number): boolean {\n if (typeof name !== \"string\" || !name) return false;\n // For ForwardRef/Memo wrappers the inner function name is sometimes inferred\n // from the property key (\"render\" or \"type\"). Treat those as anonymous.\n if (\n (tag === ForwardRef || tag === MemoComponent || tag === SimpleMemoComponent) &&\n INFERRED_PROPERTY_NAMES.has(name)\n ) {\n return false;\n }\n return true;\n}\n\n/**\n * Derive the display name from a fiber's `type` field.\n *\n * Resolution order:\n * 1. `type.displayName`\n * 2. `type.name` (function/class name — unless inferred from a property key)\n * 3. For forwardRef wrappers: inner `render.displayName` / `render.name`\n * 4. For memo wrappers: inner `type.displayName` / `type.name`\n * 5. String tags for host elements (\"div\", \"span\", …)\n * 6. Fallback: \"Anonymous\"\n */\nexport function extractName(fiber: Fiber): string {\n const { type, tag } = fiber;\n\n if (type === null || type === undefined) {\n if (tag === HostRoot) return \"HostRoot\";\n if (tag === Fragment) return \"Fragment\";\n if (tag === HostText) return \"#text\";\n return \"Anonymous\";\n }\n\n // String type = host element\n if (typeof type === \"string\") {\n return type;\n }\n\n // Direct displayName (always preferred — user explicitly set this)\n if (typeof type.displayName === \"string\" && type.displayName) {\n return type.displayName;\n }\n\n // ForwardRef — React wraps the component in an object with `render`\n if (tag === ForwardRef || (type.$$typeof && String(type.$$typeof).includes(\"forward_ref\"))) {\n const render = type.render;\n if (render) {\n if (typeof render.displayName === \"string\" && render.displayName) return render.displayName;\n if (isUserSuppliedName(render.name, tag)) return render.name as string;\n }\n return \"ForwardRef\";\n }\n\n // Memo — React wraps in an object with `type`\n if (\n tag === MemoComponent ||\n tag === SimpleMemoComponent ||\n (type.$$typeof && String(type.$$typeof).includes(\"memo\"))\n ) {\n const inner = type.type;\n if (inner) {\n if (typeof inner.displayName === \"string\" && inner.displayName) return inner.displayName;\n if (isUserSuppliedName(inner.name, tag)) return inner.name as string;\n }\n return \"Memo\";\n }\n\n // Standard function/class name\n if (isUserSuppliedName(type.name, tag)) {\n return type.name as string;\n }\n\n return \"Anonymous\";\n}\n\n// ---------------------------------------------------------------------------\n// Component type classification\n// ---------------------------------------------------------------------------\n\n/**\n * Map a fiber tag (and optionally the `type` object's `$$typeof`) to one of\n * our `ComponentType` discriminants.\n */\nexport function classifyType(fiber: Fiber): ComponentType {\n const { tag, type } = fiber;\n\n switch (tag) {\n case FunctionComponent:\n case IndeterminateComponent:\n return \"function\";\n\n case ClassComponent:\n return \"class\";\n\n case ForwardRef:\n return \"forward_ref\";\n\n case MemoComponent:\n case SimpleMemoComponent:\n return \"memo\";\n\n case HostComponent:\n case HostText:\n return \"host\";\n\n default:\n // For tags we don't explicitly map, inspect `$$typeof` if present\n if (type && typeof type === \"object\") {\n const typeofStr = String(type.$$typeof ?? \"\");\n if (typeofStr.includes(\"forward_ref\")) return \"forward_ref\";\n if (typeofStr.includes(\"memo\")) return \"memo\";\n }\n return \"function\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Source location extraction\n// ---------------------------------------------------------------------------\n\nfunction extractSource(fiber: Fiber): SourceLocation | null {\n // Standard babel-plugin-transform-react-jsx-source injects _debugSource\n if (fiber._debugSource) {\n const { fileName, lineNumber, columnNumber } = fiber._debugSource;\n return {\n fileName: String(fileName),\n lineNumber: Number(lineNumber),\n columnNumber: Number(columnNumber),\n };\n }\n\n // Our babel plugin might inject __scopeSource into memoizedProps\n const scopeSource = fiber.memoizedProps?.__scopeSource;\n if (scopeSource && typeof scopeSource === \"object\") {\n const { fileName, lineNumber, columnNumber } = scopeSource as {\n fileName: unknown;\n lineNumber: unknown;\n columnNumber: unknown;\n };\n if (\n typeof fileName === \"string\" &&\n typeof lineNumber === \"number\" &&\n typeof columnNumber === \"number\"\n ) {\n return { fileName, lineNumber, columnNumber };\n }\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Skip predicate\n// ---------------------------------------------------------------------------\n\n/**\n * Return `true` for fibers we should not emit as `ComponentNode`s.\n *\n * We always skip:\n * - HostRoot (internal React root container)\n * - HostText (raw text nodes)\n * - Fragment, SuspenseComponent wrappers\n *\n * We conditionally skip:\n * - HostComponent (\"div\", \"span\", …) — controlled by `includeHostElements`\n */\nfunction shouldSkip(fiber: Fiber, includeHost: boolean): boolean {\n const { tag } = fiber;\n\n // Always skip internal bookkeeping nodes\n if (tag === HostRoot || tag === HostText || tag === Fragment || tag === SuspenseComponent) {\n return true;\n }\n\n // Host elements: skip by default\n if (tag === HostComponent && !includeHost) {\n return true;\n }\n\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Core walker\n// ---------------------------------------------------------------------------\n\n/**\n * Walk a fiber and all its descendants, collecting `ComponentNode`s.\n *\n * @param rootFiber - The starting fiber.\n * @param options - Walk configuration.\n * @returns The `ComponentNode` for `rootFiber`, or `null` if the root should\n * be skipped. Children are populated recursively.\n */\nexport function walkFiber(fiber: Fiber | null, options: WalkOptions = {}): ComponentNode | null {\n if (fiber === null || fiber === undefined) return null;\n\n const includeHost = options.includeHostElements ?? false;\n return walkFiberInner(fiber, includeHost, new Set<Fiber>());\n}\n\nfunction walkFiberInner(\n fiber: Fiber | null | undefined,\n includeHost: boolean,\n visited: Set<Fiber>,\n): ComponentNode | null {\n if (fiber === null || fiber === undefined) return null;\n\n // Cycle guard — should not happen in a healthy fiber tree\n if (visited.has(fiber)) return null;\n\n // Check skip BEFORE adding to visited so that the transparent-skip path in\n // collectChildren can still promote this fiber's children.\n if (shouldSkip(fiber, includeHost)) {\n return null;\n }\n\n visited.add(fiber);\n\n // Assign ID first (parent before children) for predictable sequential IDs\n const id = typeof fiber._debugID === \"number\" ? fiber._debugID : nextId();\n const profilingData = getProfilingData(id);\n\n // Collect child nodes by walking child + sibling chains\n const children: ComponentNode[] = collectChildren(fiber, includeHost, visited);\n\n const node: ComponentNode = {\n id,\n name: extractName(fiber),\n type: classifyType(fiber),\n source: extractSource(fiber),\n props: serialize(fiber.memoizedProps ?? {}),\n state: extractHooks(fiber),\n context: extractContextConsumptions(fiber),\n renderCount: profilingData?.renderCount ?? 1,\n renderDuration: profilingData?.renderDuration ?? 0,\n children,\n };\n\n return node;\n}\n\n/**\n * Collect the `ComponentNode` children of a fiber by walking its `child`\n * fiber and then all subsequent `sibling` fibers.\n *\n * Skipped fibers are transparent — their own children are promoted up.\n */\nfunction collectChildren(fiber: Fiber, includeHost: boolean, visited: Set<Fiber>): ComponentNode[] {\n const nodes: ComponentNode[] = [];\n let current: Fiber | null = fiber.child ?? null;\n\n while (current !== null) {\n if (visited.has(current)) {\n current = current.sibling ?? null;\n continue;\n }\n\n if (shouldSkip(current, includeHost)) {\n // Transparent skip: this node is invisible, promote its children upward.\n // We do NOT add to visited here so that cycle guard still works correctly\n // if the same skipped node appears elsewhere (which shouldn't happen in\n // practice, but defensively correct).\n const promoted = collectChildren(current, includeHost, visited);\n nodes.push(...promoted);\n } else {\n const node = walkFiberInner(current, includeHost, visited);\n if (node !== null) {\n nodes.push(node);\n }\n }\n\n current = current.sibling ?? null;\n }\n\n return nodes;\n}\n\n// ---------------------------------------------------------------------------\n// Walk from a fiber root object (as returned by DevTools hook)\n// ---------------------------------------------------------------------------\n\n/**\n * Walk a fiber root (the object stored in `ReactRenderer.fiberRoots`) and\n * return the root `ComponentNode`, or `null` if the tree is empty.\n *\n * `fiberRoot.current` is the `HostRoot` fiber — we skip it and return the\n * first meaningful child.\n */\n// biome-ignore lint/suspicious/noExplicitAny: React DevTools fiber root shape\nexport function walkFiberRoot(fiberRoot: any, options: WalkOptions = {}): ComponentNode | null {\n if (!fiberRoot) return null;\n\n const hostRootFiber: Fiber | null = fiberRoot.current ?? null;\n if (!hostRootFiber) return null;\n\n const includeHost = options.includeHostElements ?? false;\n const visited = new Set<Fiber>();\n\n // The HostRoot itself is skipped. Collect its children directly.\n const children = collectChildren(hostRootFiber, includeHost, visited);\n\n if (children.length === 0) return null;\n if (children.length === 1) return children[0] ?? null;\n\n // Multiple root children (rare) — synthesise a wrapper\n return {\n id: nextId(),\n name: \"Root\",\n type: \"function\",\n source: null,\n props: serialize({}),\n state: [],\n context: [],\n renderCount: 1,\n renderDuration: 0,\n children,\n };\n}\n","/**\n * suspense-detector.ts\n *\n * Detects `<Suspense>` boundaries in the fiber tree and determines their\n * current status at capture time.\n *\n * React stores Suspense state in the fiber's `memoizedState` field using an\n * internal linked-list structure. The first node in the list is the dehydrated\n * / retrying state object when the boundary is suspended.\n *\n * Status heuristics (based on React internals):\n *\n * resolved — `memoizedState === null`\n * The boundary rendered its normal children successfully.\n *\n * pending — `memoizedState.dehydrated` is set, OR the state object\n * contains a thenable (`then` function) anywhere at the top\n * level, indicating React is still waiting for data.\n *\n * fallback — `memoizedState` is non-null but does not look like a pending\n * thenable; the fallback subtree is being rendered. This covers\n * the case where the promise has been thrown but not yet\n * resolved, and React is showing the fallback UI.\n *\n * Note: these are approximations over undocumented internals. React does not\n * expose a public API for querying Suspense status from outside the component.\n */\n\nimport type { SuspenseBoundaryInfo } from \"@agent-scope/core\";\nimport type { Fiber } from \"./fiber-walker.js\";\n\n// ---------------------------------------------------------------------------\n// Fiber tag constants\n// ---------------------------------------------------------------------------\n\nconst SuspenseComponent = 13;\nconst HostText = 6;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extract a display name for the component that *contains* this Suspense\n * boundary, i.e. the nearest named ancestor.\n */\nfunction nearestAncestorName(fiber: Fiber): string {\n let current: Fiber | null = fiber.return ?? null;\n while (current !== null) {\n const { type } = current;\n if (type && typeof type !== \"string\") {\n const name: unknown =\n (type as { displayName?: unknown }).displayName ?? (type as { name?: unknown }).name;\n if (typeof name === \"string\" && name) return name;\n }\n current = current.return ?? null;\n }\n return \"Unknown\";\n}\n\n/**\n * Determine the name of the fallback element (if identifiable).\n *\n * The fallback is the *second* child of a Suspense fiber — React renders the\n * primary child tree first, then attaches the fallback as a sibling. When\n * suspended, the primary tree is hidden and the fallback is shown.\n *\n * Returns `null` when the fallback is a plain text node or not identifiable.\n */\nfunction extractFallbackName(fiber: Fiber): string | null {\n // The fallback is typically the second child of the Suspense fiber\n const primary = fiber.child ?? null;\n const fallback = primary?.sibling ?? null;\n if (!fallback) return null;\n\n const { type, tag } = fallback;\n if (tag === HostText) return null;\n if (typeof type === \"string\") return type; // host element, e.g. \"div\"\n if (type && typeof type.displayName === \"string\" && type.displayName) return type.displayName;\n if (type && typeof type.name === \"string\" && type.name) return type.name;\n return null;\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: React fiber internals are untyped\ntype SuspenseMemoizedState = any;\n\n/**\n * Classify the Suspense boundary status from `memoizedState`.\n *\n * - `null` → resolved (primary content visible)\n * - dehydrated → pending (SSR dehydrated boundary, not yet hydrated)\n * - has thenable → pending (a Promise was thrown, still in-flight)\n * - non-null → fallback (suspended, showing fallback UI)\n */\nfunction classifyStatus(memoizedState: SuspenseMemoizedState): SuspenseBoundaryInfo[\"isSuspended\"] {\n if (memoizedState === null || memoizedState === undefined) {\n // resolved\n return false;\n }\n\n // Dehydrated SSR boundary\n if (\n typeof memoizedState === \"object\" &&\n memoizedState.dehydrated !== undefined &&\n memoizedState.dehydrated !== null\n ) {\n return true; // pending\n }\n\n // Thenable at top level of state object (React stores the thrown promise)\n if (typeof memoizedState === \"object\" && typeof memoizedState.then === \"function\") {\n return true; // pending\n }\n\n // Non-null state but no thenable → fallback is being shown\n return true; // fallback / suspended\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Walk the fiber tree and collect `SuspenseBoundaryInfo` for every\n * `<Suspense>` boundary found.\n *\n * @param rootFiber - Starting fiber (typically the HostRoot's first child).\n * @returns Flat list of Suspense boundary descriptors.\n */\nexport function detectSuspenseBoundaries(rootFiber: Fiber | null): SuspenseBoundaryInfo[] {\n const results: SuspenseBoundaryInfo[] = [];\n const visited = new Set<Fiber>();\n\n function walk(fiber: Fiber | null): void {\n if (fiber === null || fiber === undefined) return;\n if (visited.has(fiber)) return;\n visited.add(fiber);\n\n if (fiber.tag === SuspenseComponent) {\n const isSuspended = classifyStatus(fiber.memoizedState);\n const componentName = nearestAncestorName(fiber);\n const fallbackName = extractFallbackName(fiber);\n\n // Use _debugID when available for a stable ID, otherwise fall back to\n // the fiber's index within its parent\n const id: number = typeof fiber._debugID === \"number\" ? fiber._debugID : fiber.index;\n\n results.push({\n id,\n componentName,\n isSuspended,\n suspendedDuration: null, // timing not available at capture time\n fallbackName,\n source: fiber._debugSource\n ? {\n fileName: String(fiber._debugSource.fileName),\n lineNumber: Number(fiber._debugSource.lineNumber),\n columnNumber: Number(fiber._debugSource.columnNumber),\n }\n : null,\n });\n }\n\n walk(fiber.child ?? null);\n walk(fiber.sibling ?? null);\n }\n\n walk(rootFiber);\n return results;\n}\n","/**\n * capture.ts\n *\n * High-level `capture()` function — wires together the DevTools hook and fiber\n * walker to produce a partial `PageReport`.\n */\n\nimport type { CapturedError, PageReport, SuspenseBoundaryInfo } from \"@agent-scope/core\";\nimport {\n clearConsoleEntries,\n getConsoleEntries,\n installConsoleInterceptor,\n uninstallConsoleInterceptor,\n} from \"./console-interceptor.js\";\nimport { getHook, installHook, waitForReact } from \"./devtools-hook.js\";\nimport { detectErrors } from \"./error-detector.js\";\nimport type { WalkOptions } from \"./fiber-walker.js\";\nimport { walkFiberRoot } from \"./fiber-walker.js\";\nimport { installProfiler } from \"./profiler.js\";\nimport { detectSuspenseBoundaries } from \"./suspense-detector.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface CaptureOptions extends WalkOptions {\n /**\n * URL to record in the report.\n * Defaults to `window.location.href` in a browser context.\n */\n url?: string;\n /**\n * Timeout in milliseconds to wait for React to boot before giving up.\n * Default: 10 000.\n */\n reactTimeout?: number;\n}\n\n/** The fields populated by `capture()`. The rest can be added by callers. */\nexport type CaptureResult = Pick<\n PageReport,\n \"url\" | \"timestamp\" | \"capturedIn\" | \"tree\" | \"consoleEntries\" | \"errors\" | \"suspenseBoundaries\"\n>;\n\n// ---------------------------------------------------------------------------\n// capture()\n// ---------------------------------------------------------------------------\n\n/**\n * Capture a snapshot of the current React component tree.\n *\n * Ensures the DevTools hook is installed, waits for React to register a\n * renderer (if it hasn't already), then walks the first available fiber root.\n *\n * Console messages emitted during the capture window are recorded via the\n * console interceptor and included in the returned `consoleEntries` field.\n *\n * Also detects error boundaries that have caught errors and Suspense\n * boundaries with their current suspension status.\n *\n * @returns A partial `PageReport` containing `url`, `timestamp`, `capturedIn`,\n * `tree`, `consoleEntries`, `errors`, and `suspenseBoundaries`.\n * @throws If no React renderer registers within `reactTimeout` ms, or if the\n * fiber tree is empty.\n */\nexport async function capture(options: CaptureOptions = {}): Promise<CaptureResult> {\n const startTime = Date.now();\n\n // Ensure the hook is installed and profiler is wired\n const hook = installHook();\n installProfiler(hook);\n\n // Install console interceptor and start fresh\n installConsoleInterceptor();\n clearConsoleEntries();\n\n // Resolve the URL\n const url = options.url ?? (typeof window !== \"undefined\" ? window.location.href : \"unknown\");\n\n try {\n // Wait for a renderer\n const renderer = await waitForReact(options.reactTimeout ?? 10_000);\n\n // Grab the first fiber root from the renderer\n const fiberRoot = Array.from(renderer.fiberRoots)[0] ?? null;\n\n if (!fiberRoot) {\n throw new Error(\n \"capture(): React renderer registered but no fiber roots found. \" +\n \"Make sure React has rendered at least one component.\",\n );\n }\n\n const walkOptions: WalkOptions = {\n includeHostElements: options.includeHostElements ?? false,\n };\n\n const tree = walkFiberRoot(fiberRoot, walkOptions);\n\n if (!tree) {\n throw new Error(\n \"capture(): Fiber tree is empty. \" + \"Make sure React has rendered at least one component.\",\n );\n }\n\n // The HostRoot fiber is fiberRoot.current; walk from its first child for\n // error/suspense detection so we cover the same subtree as walkFiberRoot.\n const hostRootFiber = fiberRoot.current ?? null;\n const rootChild = hostRootFiber?.child ?? null;\n\n const errors: CapturedError[] = detectErrors(rootChild);\n const suspenseBoundaries: SuspenseBoundaryInfo[] = detectSuspenseBoundaries(rootChild);\n\n const capturedIn = Date.now() - startTime;\n\n // Collect all console entries recorded during the capture window\n const consoleEntries = getConsoleEntries();\n\n return {\n url,\n timestamp: startTime,\n capturedIn,\n tree,\n consoleEntries,\n errors,\n suspenseBoundaries,\n };\n } finally {\n // Always uninstall the interceptor to restore the original console\n uninstallConsoleInterceptor();\n }\n}\n\n// ---------------------------------------------------------------------------\n// installHook re-export (convenience)\n// ---------------------------------------------------------------------------\nexport { installHook, getHook };\n","/**\n * @agent-scope/runtime\n *\n * Browser instrumentation — captures React component trees at runtime.\n * Depends on @agent-scope/core for types.\n *\n * @packageDocumentation\n */\n\n// ---------------------------------------------------------------------------\n// Re-export shared types from @agent-scope/core\n// ---------------------------------------------------------------------------\nexport type {\n CapturedError,\n ComponentNode,\n PageReport,\n SuspenseBoundaryInfo,\n} from \"@agent-scope/core\";\nexport type { CaptureOptions, CaptureResult } from \"./capture.js\";\n// ---------------------------------------------------------------------------\n// Capture\n// ---------------------------------------------------------------------------\nexport { capture } from \"./capture.js\";\n// ---------------------------------------------------------------------------\n// Console interceptor\n// ---------------------------------------------------------------------------\nexport {\n clearConsoleEntries,\n getConsoleEntries,\n installConsoleInterceptor,\n uninstallConsoleInterceptor,\n} from \"./console-interceptor.js\";\nexport type { ReactRenderer, ScopeDevToolsHook } from \"./devtools-hook.js\";\n// ---------------------------------------------------------------------------\n// DevTools hook\n// ---------------------------------------------------------------------------\nexport {\n getHook,\n getRenderers,\n installHook,\n waitForReact,\n} from \"./devtools-hook.js\";\n// ---------------------------------------------------------------------------\n// Error detection\n// ---------------------------------------------------------------------------\nexport { detectErrors } from \"./error-detector.js\";\nexport type { Fiber, WalkOptions } from \"./fiber-walker.js\";\n// ---------------------------------------------------------------------------\n// Fiber walker\n// ---------------------------------------------------------------------------\nexport { classifyType, extractName, walkFiber, walkFiberRoot } from \"./fiber-walker.js\";\n// ---------------------------------------------------------------------------\n// Hooks extractor\n// ---------------------------------------------------------------------------\nexport { extractHooks } from \"./hooks-extractor.js\";\n// ---------------------------------------------------------------------------\n// Profiler\n// ---------------------------------------------------------------------------\nexport type { ProfilingSnapshot } from \"./profiler.js\";\nexport {\n getProfilingData,\n installProfiler,\n resetProfilingData,\n} from \"./profiler.js\";\n// ---------------------------------------------------------------------------\n// Suspense detection\n// ---------------------------------------------------------------------------\nexport { detectSuspenseBoundaries } from \"./suspense-detector.js\";\n\n// ---------------------------------------------------------------------------\n// Legacy ScopeRuntime class (stub compatibility shim)\n// ---------------------------------------------------------------------------\n\nimport type { ComponentNode, PageReport } from \"@agent-scope/core\";\n\n/** Options for initializing the Scope runtime */\nexport interface RuntimeOptions {\n /** Called whenever a new PageReport is captured */\n onCapture?: (report: PageReport) => void;\n /** Maximum number of reports to buffer before evicting the oldest */\n bufferSize?: number;\n}\n\n/** Manages an active capture session */\nexport class ScopeRuntime {\n private readonly buffer: PageReport[] = [];\n private readonly options: Required<Pick<RuntimeOptions, \"bufferSize\">> &\n Pick<RuntimeOptions, \"onCapture\">;\n\n constructor(options: RuntimeOptions = {}) {\n this.options = {\n bufferSize: options.bufferSize ?? 100,\n onCapture: options.onCapture,\n };\n }\n\n /** Record a captured PageReport */\n record(report: PageReport): void {\n if (this.buffer.length >= this.options.bufferSize) {\n this.buffer.shift();\n }\n this.buffer.push(report);\n this.options.onCapture?.(report);\n }\n\n /** Return all buffered reports and clear the buffer */\n flush(): PageReport[] {\n return this.buffer.splice(0);\n }\n\n /** Return a read-only snapshot of the buffer */\n getBuffer(): readonly PageReport[] {\n return this.buffer;\n }\n\n /** Find a node by fiber ID within a component tree */\n static findNode(root: ComponentNode, id: number): ComponentNode | null {\n if (root.id === id) return root;\n for (const child of root.children) {\n const found = ScopeRuntime.findNode(child, id);\n if (found !== null) return found;\n }\n return null;\n }\n}\n\n/** Create and return a new ScopeRuntime instance */\nexport function createRuntime(options?: RuntimeOptions): ScopeRuntime {\n return new ScopeRuntime(options);\n}\n"]}
1
+ {"version":3,"sources":["../src/console-interceptor.ts","../src/devtools-hook.ts","../src/error-detector.ts","../src/context-extractor.ts","../src/hooks-extractor.ts","../src/profiler.ts","../src/fiber-walker.ts","../src/suspense-detector.ts","../src/capture.ts","../src/index.ts"],"names":["serialize","_installed","ClassComponent","HookLayout","SuspenseComponent","HostText","tree"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * console-interceptor.ts\n *\n * Monkey-patches `console.log`, `console.warn`, `console.error`,\n * `console.info`, `console.debug`, `console.group`, `console.groupCollapsed`,\n * `console.table`, and `console.trace` to capture messages with React\n * component attribution.\n *\n * Component attribution is resolved by reading the DevTools hook's\n * currently-active fiber (set during React render). When no fiber is active\n * (effect, event handler, async callback) `componentName` is `null`.\n *\n * The interceptor never suppresses output — every patched method calls the\n * original implementation with all original arguments.\n */\n\nimport type { ConsoleEntry, ConsoleLevel } from \"@agent-scope/core\";\nimport { serialize } from \"@agent-scope/core\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** All console levels we intercept. */\nconst INTERCEPTED_LEVELS: ConsoleLevel[] = [\n \"log\",\n \"warn\",\n \"error\",\n \"info\",\n \"debug\",\n \"group\",\n \"groupCollapsed\",\n \"table\",\n \"trace\",\n];\n\n// ---------------------------------------------------------------------------\n// Internal state\n// ---------------------------------------------------------------------------\n\n/** Captured entries since last `clearConsoleEntries()`. */\nconst _entries: ConsoleEntry[] = [];\n\n/** Original console methods saved at `install()` time. */\nconst _originals: Partial<Record<ConsoleLevel, (...args: unknown[]) => void>> = {};\n\n/** Whether the interceptor is currently installed. */\nlet _installed = false;\n\n// ---------------------------------------------------------------------------\n// Component attribution\n// ---------------------------------------------------------------------------\n\n/**\n * Attempt to discover the currently-rendering component name by inspecting\n * the React DevTools global hook.\n *\n * React sets `__REACT_DEVTOOLS_GLOBAL_HOOK__._currentFiber` (or an equivalent\n * field) to the active fiber during synchronous render work. This is the\n * same mechanism used by the React DevTools extension.\n *\n * Returns `null` when:\n * - No hook is installed\n * - No fiber is currently active (we're outside a render)\n */\nfunction getCurrentComponentName(): string | null {\n try {\n // Access the global hook\n const win =\n typeof window !== \"undefined\"\n ? window\n : typeof globalThis !== \"undefined\"\n ? globalThis\n : null;\n if (!win) return null;\n\n // biome-ignore lint/suspicious/noExplicitAny: accessing undocumented React internals\n const hook = (win as any).__REACT_DEVTOOLS_GLOBAL_HOOK__;\n if (!hook || typeof hook !== \"object\") return null;\n\n // React 18+ stores the current fiber in `_currentFiber` during render.\n // biome-ignore lint/suspicious/noExplicitAny: undocumented React internals\n const fiber: any = hook._currentFiber ?? hook.currentFiber ?? null;\n if (!fiber) return null;\n\n return extractFiberName(fiber);\n } catch {\n return null;\n }\n}\n\n/**\n * Extract a human-readable component name from a React fiber object.\n * Mirrors the logic in `fiber-walker.ts#extractName`.\n */\n// biome-ignore lint/suspicious/noExplicitAny: opaque fiber\nfunction extractFiberName(fiber: any): string | null {\n if (!fiber) return null;\n\n const { type } = fiber;\n if (!type) return null;\n\n // Function component or class component\n if (typeof type === \"function\") {\n return type.displayName || type.name || null;\n }\n\n // Forwarded refs: { $$typeof, render }\n if (typeof type === \"object\" && type !== null) {\n if (typeof type.displayName === \"string\" && type.displayName) {\n return type.displayName;\n }\n if (typeof type.render === \"function\") {\n return type.render.displayName || type.render.name || null;\n }\n // React.memo wraps: { $$typeof, type }\n if (type.type) {\n return extractFiberName({ type: type.type });\n }\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Preview builder\n// ---------------------------------------------------------------------------\n\n/**\n * Build a condensed single-line text preview from raw console arguments.\n *\n * Concatenates string representations of each argument, separated by spaces,\n * trimmed to 200 characters.\n */\nfunction buildPreview(args: unknown[]): string {\n const MAX = 200;\n const parts = args.map((arg) => {\n if (arg === null) return \"null\";\n if (arg === undefined) return \"undefined\";\n if (typeof arg === \"string\") return arg;\n if (typeof arg === \"number\" || typeof arg === \"boolean\" || typeof arg === \"bigint\") {\n return String(arg);\n }\n try {\n return JSON.stringify(arg);\n } catch {\n return String(arg);\n }\n });\n\n const joined = parts.join(\" \");\n return joined.length > MAX ? `${joined.slice(0, MAX - 1)}…` : joined;\n}\n\n// ---------------------------------------------------------------------------\n// Core interceptor factory\n// ---------------------------------------------------------------------------\n\nfunction makeWrapper(\n level: ConsoleLevel,\n original: (...args: unknown[]) => void,\n): (...args: unknown[]) => void {\n return function scopeConsoleWrapper(...args: unknown[]): void {\n // Always call through first so the console output is never suppressed\n original.apply(console, args);\n\n try {\n const componentName = getCurrentComponentName();\n const timestamp = Date.now();\n const serializedArgs = args.map((a) => serialize(a));\n const preview = buildPreview(args);\n\n const entry: ConsoleEntry = {\n level,\n args: serializedArgs,\n componentName,\n timestamp,\n preview,\n };\n\n _entries.push(entry);\n } catch {\n // Never let interceptor errors propagate — capture is best-effort\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Install the console interceptor.\n *\n * Replaces `console.log`, `console.warn`, `console.error`, `console.info`,\n * `console.debug`, `console.group`, `console.groupCollapsed`, `console.table`,\n * and `console.trace` with wrappers that record entries.\n *\n * Idempotent — calling `install` twice without `uninstall` in between is safe.\n */\nexport function installConsoleInterceptor(): void {\n if (_installed) return;\n _installed = true;\n\n for (const level of INTERCEPTED_LEVELS) {\n const original = console[level] as (...args: unknown[]) => void;\n _originals[level] = original;\n // biome-ignore lint/suspicious/noExplicitAny: intentional monkey-patch\n (console as any)[level] = makeWrapper(level, original);\n }\n}\n\n/**\n * Uninstall the console interceptor and restore all original methods.\n *\n * Idempotent — safe to call even if the interceptor is not installed.\n */\nexport function uninstallConsoleInterceptor(): void {\n if (!_installed) return;\n _installed = false;\n\n for (const level of INTERCEPTED_LEVELS) {\n const original = _originals[level];\n if (original !== undefined) {\n // biome-ignore lint/suspicious/noExplicitAny: restoring monkey-patch\n (console as any)[level] = original;\n }\n delete _originals[level];\n }\n}\n\n/**\n * Return a snapshot of all captured `ConsoleEntry` objects since the last\n * `clearConsoleEntries()` call (or since install).\n *\n * The returned array is a shallow copy — mutations do not affect the buffer.\n */\nexport function getConsoleEntries(): ConsoleEntry[] {\n return _entries.slice();\n}\n\n/**\n * Clear the captured entries buffer.\n */\nexport function clearConsoleEntries(): void {\n _entries.splice(0);\n}\n\n// ---------------------------------------------------------------------------\n// Internal reset helper (test only)\n// ---------------------------------------------------------------------------\n\n/**\n * @internal\n * Reset all module-level state. Used in unit tests to get a clean slate.\n */\nexport function _resetForTesting(): void {\n if (_installed) {\n uninstallConsoleInterceptor();\n }\n clearConsoleEntries();\n}\n","/**\n * devtools-hook.ts\n *\n * Installs and manages the React DevTools global hook\n * (`window.__REACT_DEVTOOLS_GLOBAL_HOOK__`).\n *\n * React checks for this hook at module initialisation time, so it MUST be\n * installed before any React bundle is evaluated. Call `installHook()` as\n * early as possible (e.g. the very first script on the page).\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal shape of a React renderer as surfaced through the DevTools hook.\n *\n * React passes a much larger object; we only reference the fields we need.\n */\nexport interface ReactRenderer {\n /** Opaque renderer ID assigned by the hook on injection. */\n id: number;\n /** The renderer object passed by React via `inject()`. */\n // biome-ignore lint/suspicious/noExplicitAny: opaque React internals\n renderer: any;\n /** Set of fiber root containers managed by this renderer. */\n // biome-ignore lint/suspicious/noExplicitAny: opaque React internals\n fiberRoots: Set<any>;\n}\n\n/**\n * The shape we install at `window.__REACT_DEVTOOLS_GLOBAL_HOOK__`.\n *\n * React calls `inject(renderer)` when it boots, giving us access to its\n * internal fiber roots. Everything else is just enough scaffolding to keep\n * React happy.\n */\nexport interface ScopeDevToolsHook {\n /** Required by React – signals that DevTools are present. */\n isDisabled: false;\n /** Required by React – signals DevTools support for profiling. */\n supportsFiber: true;\n /**\n * Called by React when it initialises a new renderer instance.\n * Returns the renderer's numeric ID.\n */\n inject(renderer: unknown): number;\n /** Called by React before each commit (we no-op this). */\n onCommitFiberRoot(rendererID: number, root: unknown, priorityLevel: unknown): void;\n /** Called by React when an unmount occurs (we no-op this). */\n onCommitFiberUnmount(rendererID: number, fiber: unknown): void;\n /** Called by React before post-commit effects (we no-op this). */\n onPostCommitFiberRoot(rendererID: number, root: unknown): void;\n /** Extension point: registered renderers keyed by ID. */\n _renderers: Map<number, ReactRenderer>;\n /** Whether the hook was installed by Scope (vs. pre-existing DevTools). */\n _isScopeHook: true;\n}\n\n// ---------------------------------------------------------------------------\n// Internal state\n// ---------------------------------------------------------------------------\n\n/**\n * The installed hook instance (null until `installHook()` is called or a\n * pre-existing hook is found).\n */\nlet _hook: ScopeDevToolsHook | null = null;\n\n/** Auto-incrementing renderer ID counter. */\nlet _nextRendererID = 1;\n\n/** Listeners waiting for the first renderer registration. */\nconst _rendererListeners: Array<(renderer: ReactRenderer) => void> = [];\n\n// ---------------------------------------------------------------------------\n// Hook factory\n// ---------------------------------------------------------------------------\n\nfunction createScopeHook(): ScopeDevToolsHook {\n const renderers = new Map<number, ReactRenderer>();\n\n const hook: ScopeDevToolsHook = {\n isDisabled: false,\n supportsFiber: true,\n _renderers: renderers,\n _isScopeHook: true,\n\n inject(renderer: unknown): number {\n const id = _nextRendererID++;\n const entry: ReactRenderer = {\n id,\n renderer,\n // biome-ignore lint/suspicious/noExplicitAny: React renderer internals\n fiberRoots: new Set<any>(),\n };\n renderers.set(id, entry);\n\n // Notify any waiting listeners\n for (const listener of _rendererListeners.splice(0)) {\n listener(entry);\n }\n\n return id;\n },\n\n onCommitFiberRoot(rendererID: number, root: unknown, _priorityLevel: unknown): void {\n const entry = renderers.get(rendererID);\n if (entry) {\n entry.fiberRoots.add(root);\n }\n },\n\n onCommitFiberUnmount(_rendererID: number, _fiber: unknown): void {\n // no-op — we don't track individual unmounts\n },\n\n onPostCommitFiberRoot(_rendererID: number, _root: unknown): void {\n // no-op\n },\n };\n\n return hook;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Install the Scope DevTools hook at `window.__REACT_DEVTOOLS_GLOBAL_HOOK__`.\n *\n * - If no hook exists yet, installs a new Scope hook.\n * - If a Scope hook is already installed, returns the existing instance.\n * - If a *third-party* hook is already present (e.g. real React DevTools),\n * we patch it minimally so that renderer registrations are forwarded to us\n * as well.\n *\n * Must be called **before React is loaded** to intercept `inject()`.\n */\nexport function installHook(): ScopeDevToolsHook {\n if (_hook !== null) {\n return _hook;\n }\n\n // Safe check for browser globals\n const win =\n typeof window !== \"undefined\"\n ? (window as Window &\n typeof globalThis & {\n __REACT_DEVTOOLS_GLOBAL_HOOK__?: unknown;\n })\n : null;\n\n if (win === null) {\n // Non-browser environment (Node test, SSR) — create a detached hook\n _hook = createScopeHook();\n return _hook;\n }\n\n const existing = win.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n\n if (existing && typeof existing === \"object\") {\n const existingHook = existing as Record<string, unknown>;\n\n // Already our hook\n if (existingHook._isScopeHook === true) {\n _hook = existing as ScopeDevToolsHook;\n return _hook;\n }\n\n // A third-party hook (real DevTools) exists — patch inject() to also\n // forward to our renderer registry.\n const scopeHook = createScopeHook();\n const originalInject = existingHook.inject as ((renderer: unknown) => number) | undefined;\n\n existingHook.inject = (renderer: unknown): number => {\n const originalId =\n typeof originalInject === \"function\" ? originalInject.call(existing, renderer) : -1;\n scopeHook.inject(renderer);\n return originalId;\n };\n\n // Keep _renderers accessible from the patched hook\n existingHook._renderers = scopeHook._renderers;\n existingHook._isScopeHook = true;\n\n _hook = scopeHook;\n return _hook;\n }\n\n // No existing hook — install ours\n _hook = createScopeHook();\n win.__REACT_DEVTOOLS_GLOBAL_HOOK__ = _hook;\n return _hook;\n}\n\n/**\n * Retrieve the currently installed hook.\n *\n * Returns `null` if `installHook()` has not yet been called.\n */\nexport function getHook(): ScopeDevToolsHook | null {\n return _hook;\n}\n\n/**\n * Return a snapshot of all registered React renderers.\n *\n * Empty until React calls `inject()`.\n */\nexport function getRenderers(): ReactRenderer[] {\n if (_hook === null) return [];\n return Array.from(_hook._renderers.values());\n}\n\n/**\n * Wait until at least one React renderer has registered with the hook.\n *\n * @param timeout - Maximum milliseconds to wait (default: 10 000).\n * @returns A promise that resolves with the first registered renderer.\n * @throws If the timeout elapses with no renderer.\n */\nexport function waitForReact(timeout = 10_000): Promise<ReactRenderer> {\n // Install if not already done\n const hook = _hook ?? installHook();\n\n // If a renderer is already registered, resolve immediately\n const existing = Array.from(hook._renderers.values());\n if (existing.length > 0) {\n return Promise.resolve(existing[0] as ReactRenderer);\n }\n\n return new Promise<ReactRenderer>((resolve, reject) => {\n const timer = setTimeout(() => {\n const idx = _rendererListeners.indexOf(listener);\n if (idx !== -1) _rendererListeners.splice(idx, 1);\n reject(new Error(`waitForReact: timed out after ${timeout}ms`));\n }, timeout);\n\n const listener = (renderer: ReactRenderer): void => {\n clearTimeout(timer);\n resolve(renderer);\n };\n\n _rendererListeners.push(listener);\n });\n}\n\n// ---------------------------------------------------------------------------\n// Internal reset helper (test only)\n// ---------------------------------------------------------------------------\n\n/**\n * @internal\n * Reset all module-level state. Used in unit tests to get a clean slate.\n */\nexport function _resetForTesting(): void {\n _hook = null;\n _nextRendererID = 1;\n _rendererListeners.splice(0);\n}\n","/**\n * error-detector.ts\n *\n * Detects React error boundaries in the fiber tree and extracts information\n * about any errors they have caught.\n *\n * React error boundaries are class components that implement at least one of:\n * - `static getDerivedStateFromError(error)` — static method\n * - `componentDidCatch(error, info)` — instance method\n *\n * When a boundary has caught an error, React stores error info in the fiber's\n * `memoizedState` (the current component state snapshot). Common patterns:\n * - `{ hasError: true, error: Error }` (class-level state)\n * - `{ error: Error }` (minimal pattern)\n *\n * We walk the fiber tree, identify boundary components, inspect their state,\n * and build `CapturedError` objects when an error is present.\n */\n\nimport type { CapturedError } from \"@agent-scope/core\";\nimport type { Fiber } from \"./fiber-walker.js\";\n\n// ---------------------------------------------------------------------------\n// Fiber tag constants\n// ---------------------------------------------------------------------------\n\nconst ClassComponent = 1;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extract a display name from a fiber — mirrors the logic in fiber-walker.ts\n * but kept local to avoid a circular dependency.\n */\nfunction fiberName(fiber: Fiber): string {\n const { type } = fiber;\n if (!type) return \"Anonymous\";\n if (typeof type === \"string\") return type;\n if (typeof type.displayName === \"string\" && type.displayName) return type.displayName;\n if (typeof type.name === \"string\" && type.name) return type.name;\n return \"Anonymous\";\n}\n\n/**\n * Return `true` when the class constructor indicates this fiber is an error\n * boundary.\n *\n * A component is an error boundary when it defines:\n * 1. `static getDerivedStateFromError` — checked on the class (type)\n * 2. `componentDidCatch` — checked on the prototype (instance method)\n */\nfunction isErrorBoundary(fiber: Fiber): boolean {\n if (fiber.tag !== ClassComponent) return false;\n const type = fiber.type;\n if (!type || typeof type !== \"function\") return false;\n\n // Static method (React 16.3+)\n if (typeof type.getDerivedStateFromError === \"function\") return true;\n\n // Instance method via prototype\n if (type.prototype && typeof type.prototype.componentDidCatch === \"function\") return true;\n\n return false;\n}\n\n/**\n * Try to extract an `Error` instance (or error-like object) from the\n * boundary's current memoized state.\n *\n * React itself does not mandate a particular state shape for error boundaries\n * — it's up to the component author. We look for the most common patterns:\n *\n * 1. `state.error instanceof Error` (most common)\n * 2. `state.hasError === true && state.error` (two-field pattern)\n * 3. `state` itself is an `Error` (rare but valid)\n */\n// biome-ignore lint/suspicious/noExplicitAny: React fiber state is untyped\nfunction extractErrorFromState(memoizedState: any): Error | null {\n if (memoizedState === null || memoizedState === undefined) return null;\n\n // Direct Error instance stored in state\n if (memoizedState instanceof Error) return memoizedState;\n\n if (typeof memoizedState !== \"object\") return null;\n\n // Standard two-field pattern: { hasError: true, error: Error }\n if (memoizedState.hasError === true && memoizedState.error instanceof Error) {\n return memoizedState.error;\n }\n\n // Simple one-field pattern: { error: Error }\n if (memoizedState.error instanceof Error) return memoizedState.error;\n\n // Some components store the error under a different key; check any value\n // that is an Error instance\n for (const key of Object.keys(memoizedState)) {\n if (memoizedState[key] instanceof Error) return memoizedState[key];\n }\n\n return null;\n}\n\n/**\n * Walk the fiber tree upward from `fiber` to find the nearest ancestor that\n * is an error boundary. Returns `null` if none is found.\n */\nfunction findNearestBoundaryName(fiber: Fiber): string | null {\n let current: Fiber | null = fiber.return ?? null;\n while (current !== null) {\n if (isErrorBoundary(current)) {\n return fiberName(current);\n }\n current = current.return ?? null;\n }\n return null;\n}\n\n/**\n * Walk the fiber tree depth-first and collect `CapturedError` entries for\n * every error boundary that is currently holding a caught error.\n *\n * @param rootFiber - Top of the fiber tree (typically `HostRoot.child`).\n * @returns Array of `CapturedError` objects; empty when nothing has been caught.\n */\nexport function detectErrors(rootFiber: Fiber | null): CapturedError[] {\n const results: CapturedError[] = [];\n const visited = new Set<Fiber>();\n\n function walk(fiber: Fiber | null): void {\n if (fiber === null || fiber === undefined) return;\n if (visited.has(fiber)) return;\n visited.add(fiber);\n\n if (isErrorBoundary(fiber)) {\n const error = extractErrorFromState(fiber.memoizedState);\n if (error !== null) {\n // The boundary itself caught the error; the throwing component is\n // typically the child that is now unmounted. We attribute it to the\n // first child of the boundary when available, otherwise to the\n // boundary component itself.\n const throwingChild = fiber.child;\n const componentName = throwingChild ? fiberName(throwingChild) : fiberName(fiber);\n const boundaryName = fiberName(fiber);\n\n // Walk upward to check for an enclosing boundary (nested boundaries)\n const enclosingBoundary = findNearestBoundaryName(fiber);\n\n results.push({\n message: error.message ?? String(error),\n name: error.name ?? \"Error\",\n stack: error.stack ?? null,\n source: null, // Stack parsing is left to consumers\n componentName,\n timestamp: Date.now(),\n capturedBy: \"boundary\",\n // Store boundary name as a non-standard extension that typed consumers\n // can access. The interface only requires the defined fields.\n ...({ boundaryName: enclosingBoundary ?? boundaryName } as Partial<CapturedError>),\n });\n }\n }\n\n walk(fiber.child ?? null);\n walk(fiber.sibling ?? null);\n }\n\n walk(rootFiber);\n return results;\n}\n","/**\n * context-extractor.ts\n *\n * Detects React context consumers and providers in a fiber tree and extracts\n * their consumed / provided values.\n *\n * React context internals we rely on:\n * - `fiber.dependencies` — linked list of context dependencies (React ≥17)\n * - `fiber.contextDependencies` — same, older React 16 name\n * - `dependency.context` — the React context object\n * - `context._currentValue` — the current provided value (primary context slot)\n * - `context.displayName` — optional human-readable name\n * - `fiber.tag === 10` — ContextProvider fiber\n * - `fiber.type._context` — context object on a provider fiber\n * - `fiber.memoizedProps.value` — value prop of a Provider\n *\n * None of these fields are part of React's public API; they are undocumented\n * implementation details that may change across React versions.\n */\n\nimport type { ContextConsumption, SerializedValue } from \"@agent-scope/core\";\nimport { serialize } from \"@agent-scope/core\";\nimport type { Fiber } from \"./fiber-walker.js\";\n\n// ---------------------------------------------------------------------------\n// Internal constants\n// ---------------------------------------------------------------------------\n\n/** Fiber tag for ContextProvider (React source: ReactWorkTags.js). */\nconst CONTEXT_PROVIDER_TAG = 10;\n\n/** Fiber tag for ContextConsumer (React source: ReactWorkTags.js). */\nconst CONTEXT_CONSUMER_TAG = 9;\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a human-readable name for a React context object.\n *\n * Resolution order:\n * 1. `context.displayName` — explicitly set by the application\n * 2. Constructor name of `_currentValue` — unreliable but a useful hint\n * 3. `null` — no name available\n */\nfunction resolveContextName(\n // biome-ignore lint/suspicious/noExplicitAny: React context internals\n context: any,\n): string | null {\n if (!context || typeof context !== \"object\") return null;\n\n if (typeof context.displayName === \"string\" && context.displayName) {\n return context.displayName;\n }\n\n // Constructor name heuristic — skip generic built-in names\n const currentValue = context._currentValue;\n if (currentValue !== null && currentValue !== undefined && typeof currentValue === \"object\") {\n const ctorName: unknown = currentValue.constructor?.name;\n if (typeof ctorName === \"string\" && ctorName && ctorName !== \"Object\" && ctorName !== \"Array\") {\n return ctorName;\n }\n }\n\n return null;\n}\n\n/**\n * Read the linked list of context dependencies off a fiber.\n *\n * React ≥17 stores them on `fiber.dependencies.firstContext`; React 16 used\n * `fiber.contextDependencies.first`. We try both locations defensively.\n *\n * Returns an empty array when no context dependencies are found.\n */\n// biome-ignore lint/suspicious/noExplicitAny: React fiber internals\nfunction readContextDependencies(fiber: Fiber): any[] {\n // React 17+\n // biome-ignore lint/suspicious/noExplicitAny: fiber internals\n const first: any =\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n (fiber as any).dependencies?.firstContext ??\n // React 16 legacy field\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n (fiber as any).contextDependencies?.first ??\n null;\n\n if (first === null || first === undefined) return [];\n\n const deps: unknown[] = [];\n let node = first;\n while (node !== null && node !== undefined) {\n deps.push(node);\n node = node.next ?? null;\n }\n return deps;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Extract all React context consumptions from a fiber.\n *\n * Reads the fiber's context dependency linked list and returns a\n * `ContextConsumption` for every context the component reads. If the fiber\n * has no context dependencies an empty array is returned.\n *\n * @param fiber - The fiber to inspect.\n * @returns An array of context consumptions (may be empty).\n */\nexport function extractContextConsumptions(fiber: Fiber): ContextConsumption[] {\n // ContextConsumer fibers (tag 9) hold their context on `fiber.type`\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n if ((fiber as any).tag === CONTEXT_CONSUMER_TAG) {\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n const context = (fiber as any).type;\n if (context && typeof context === \"object\") {\n const contextName = resolveContextName(context);\n const raw: unknown = context._currentValue;\n return [\n {\n contextName,\n value: serialize(raw as Record<string, unknown>),\n didTriggerRender: false,\n },\n ];\n }\n return [];\n }\n\n const deps = readContextDependencies(fiber);\n if (deps.length === 0) return [];\n\n const consumptions: ContextConsumption[] = [];\n\n for (const dep of deps) {\n const context = dep.context ?? dep.observedBits /* React 16 */ ?? null;\n if (!context || typeof context !== \"object\") continue;\n\n // The current value lives on _currentValue (primary slot).\n // React maintains two slots (_currentValue / _currentValue2) for\n // concurrent mode; we only read the primary slot.\n const raw: unknown = context._currentValue;\n const contextName = resolveContextName(context);\n\n consumptions.push({\n contextName,\n value: serialize(raw as Record<string, unknown>),\n didTriggerRender: false,\n });\n }\n\n return consumptions;\n}\n\n/**\n * Extract context provider information from a ContextProvider fiber (tag 10).\n *\n * For non-provider fibers this returns an empty array.\n *\n * @param fiber - The fiber to inspect.\n * @returns An array with a single entry for a provider fiber, or empty array.\n */\nexport function extractContextProviders(\n fiber: Fiber,\n): Array<{ contextName: string | null; value: SerializedValue }> {\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n if ((fiber as any).tag !== CONTEXT_PROVIDER_TAG) return [];\n\n // The context object lives at fiber.type._context on a Provider fiber.\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n const context = (fiber as any).type?._context ?? null;\n\n // The provided value is the `value` prop.\n // biome-ignore lint/suspicious/noExplicitAny: React fiber memoizedProps\n const raw: unknown = (fiber.memoizedProps as any)?.value;\n\n const contextName = context ? resolveContextName(context) : null;\n\n return [\n {\n contextName,\n value: serialize(raw as Record<string, unknown>),\n },\n ];\n}\n","/**\n * hooks-extractor.ts\n *\n * Extracts `HookState[]` from a React fiber's `memoizedState` linked list.\n *\n * React stores hooks as a singly-linked list where each node has:\n * - `memoizedState` — the hook's stored value (shape varies by hook type)\n * - `queue` — update queue present on useState / useReducer\n * - `next` — pointer to the next hook node in call order\n *\n * Hook types are NOT tagged by React, so we identify them by inspecting the\n * shape of each node (duck-typing). The heuristics below mirror the internal\n * structure documented in React's source (ReactFiberHooks.js).\n *\n * @internal\n */\n\nimport type { HookState, HookType } from \"@agent-scope/core\";\nimport { serialize } from \"@agent-scope/core\";\n\n// ---------------------------------------------------------------------------\n// React internal constants (ReactHookEffectTags.js)\n// ---------------------------------------------------------------------------\n\n/** Layout effect flag — set on `useLayoutEffect` hooks. */\nconst HookLayout = 0b00100; // 4\n\n// ---------------------------------------------------------------------------\n// Internal hook-node shape\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal structural shape of a React hook linked-list node.\n *\n * React's actual internal type is much larger; we only read the fields\n * relevant to hook extraction.\n */\ninterface HookNode {\n memoizedState: unknown;\n // biome-ignore lint/suspicious/noExplicitAny: React update queue internals\n queue: Record<string, any> | null | undefined;\n next: HookNode | null;\n}\n\n/**\n * Shape of a React effect object (the value stored in `memoizedState` for\n * `useEffect` and `useLayoutEffect` hooks).\n */\ninterface EffectObject {\n tag: number;\n create: () => unknown;\n destroy: (() => void) | null | undefined;\n deps: unknown[] | null;\n // biome-ignore lint/suspicious/noExplicitAny: React effect circular list\n next: any;\n}\n\n// ---------------------------------------------------------------------------\n// Type identification helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Return true when `node.memoizedState` looks like a React effect object.\n *\n * Effect nodes store the full effect descriptor AS their memoizedState.\n * Distinguishing traits: `create` is a function and a `deps` key exists.\n */\nfunction isEffectNode(node: HookNode): node is HookNode & { memoizedState: EffectObject } {\n const ms = node.memoizedState;\n if (ms === null || typeof ms !== \"object\") return false;\n const obj = ms as Record<string, unknown>;\n return typeof obj.create === \"function\" && \"deps\" in obj && typeof obj.tag === \"number\";\n}\n\n/**\n * Return true when `node.memoizedState` looks like a `useRef` ref object.\n *\n * React stores ref objects as `{ current: value }`. We confirm there is no\n * `queue` (which would indicate useState/useReducer instead).\n */\nfunction isRefNode(node: HookNode): boolean {\n if (node.queue != null) return false;\n const ms = node.memoizedState;\n if (ms === null || typeof ms !== \"object\" || Array.isArray(ms)) return false;\n const keys = Object.keys(ms as object);\n return keys.length === 1 && keys[0] === \"current\";\n}\n\n/**\n * Return true when `node.memoizedState` is a `[value, deps]` tuple used by\n * `useMemo` and `useCallback`.\n */\nfunction isMemoTuple(node: HookNode): boolean {\n if (node.queue != null) return false;\n const ms = node.memoizedState;\n if (!Array.isArray(ms) || ms.length !== 2) return false;\n // deps must be an array or null — if it's neither, likely not a memo tuple\n return ms[1] === null || Array.isArray(ms[1]);\n}\n\n/**\n * Return true when the node has an update queue with a `dispatch` function,\n * indicating a `useState` or `useReducer` hook.\n */\nfunction isStateOrReducerNode(node: HookNode): boolean {\n return (\n node.queue != null &&\n typeof node.queue === \"object\" &&\n typeof node.queue.dispatch === \"function\"\n );\n}\n\n/**\n * Distinguish `useReducer` from `useState` by inspecting the queue's\n * `lastRenderedReducer`.\n *\n * React's basic `useState` reducer is: `(state, action) => action` (a no-op\n * pass-through for the action). `useReducer` supplies a real reducer function\n * with a different arity / body. We can't inspect the body, but we can look\n * at whether the renderer exposed a `reducer` property on the queue or if the\n * name of `lastRenderedReducer` matches the built-in patterns.\n */\nfunction isReducerNode(node: HookNode): boolean {\n if (!isStateOrReducerNode(node)) return false;\n const q = node.queue as Record<string, unknown>;\n\n // If the queue carries an explicit `reducer` property (some React builds), trust it.\n if (typeof q.reducer === \"function\") return true;\n\n const lrr = q.lastRenderedReducer;\n if (typeof lrr !== \"function\") return false;\n\n // React names its built-in useState reducer \"basicStateReducer\". Any\n // other name strongly implies a user-supplied reducer.\n const name = (lrr as { name?: string }).name ?? \"\";\n return name !== \"basicStateReducer\" && name !== \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Effect classification\n// ---------------------------------------------------------------------------\n\nfunction classifyEffectType(effect: EffectObject): \"useEffect\" | \"useLayoutEffect\" {\n if (effect.tag & HookLayout) return \"useLayoutEffect\";\n // passive flag (0b01000) or unknown tag → default to useEffect\n return \"useEffect\";\n}\n\n// ---------------------------------------------------------------------------\n// Dependency serialisation helper\n// ---------------------------------------------------------------------------\n\nfunction serializeDeps(deps: unknown[] | null | undefined): ReturnType<typeof serialize>[] | null {\n if (deps === null || deps === undefined) return null;\n if (!Array.isArray(deps)) return null;\n return deps.map((d) => serialize(d));\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Extract an ordered list of `HookState` snapshots from a fiber's\n * `memoizedState` linked list.\n *\n * @param fiber - A React fiber object (typed as `any` because React doesn't\n * export its internal fiber shape).\n * @returns An ordered array of `HookState` entries (one per hook call),\n * or an empty array if the fiber has no hooks or is null.\n */\n// biome-ignore lint/suspicious/noExplicitAny: React fiber internals\nexport function extractHooks(fiber: any): HookState[] {\n if (fiber == null) return [];\n\n // biome-ignore lint/suspicious/noExplicitAny: React hook node internals\n let node: HookNode | null = (fiber.memoizedState as any) ?? null;\n if (node === null) return [];\n\n const hooks: HookState[] = [];\n\n while (node !== null) {\n hooks.push(classifyNode(node));\n node = node.next ?? null;\n }\n\n return hooks;\n}\n\n// ---------------------------------------------------------------------------\n// Per-node classification\n// ---------------------------------------------------------------------------\n\nfunction classifyNode(node: HookNode): HookState {\n // ── Effect hooks (useEffect / useLayoutEffect) ─────────────────────────\n if (isEffectNode(node)) {\n const effect = node.memoizedState as EffectObject;\n const hookType = classifyEffectType(effect);\n return {\n type: hookType,\n name: null,\n value: serialize(undefined),\n deps: serializeDeps(effect.deps),\n hasCleanup: typeof effect.destroy === \"function\",\n };\n }\n\n // ── useRef ────────────────────────────────────────────────────────────\n if (isRefNode(node)) {\n const ref = node.memoizedState as { current: unknown };\n return {\n type: \"useRef\",\n name: null,\n value: serialize(ref.current),\n deps: null,\n hasCleanup: null,\n };\n }\n\n // ── useMemo / useCallback ─────────────────────────────────────────────\n if (isMemoTuple(node)) {\n const [val, deps] = node.memoizedState as [unknown, unknown[] | null];\n const hookType: HookType = typeof val === \"function\" ? \"useCallback\" : \"useMemo\";\n return {\n type: hookType,\n name: null,\n value: serialize(val),\n deps: serializeDeps(deps),\n hasCleanup: null,\n };\n }\n\n // ── useState / useReducer ─────────────────────────────────────────────\n if (isStateOrReducerNode(node)) {\n const hookType: HookType = isReducerNode(node) ? \"useReducer\" : \"useState\";\n return {\n type: hookType,\n name: null,\n value: serialize(node.memoizedState),\n deps: null,\n hasCleanup: null,\n };\n }\n\n // ── Fallback: custom / unrecognised ───────────────────────────────────\n return {\n type: \"custom\",\n name: null,\n value: serialize(node.memoizedState),\n deps: null,\n hasCleanup: null,\n };\n}\n","/**\n * profiler.ts\n *\n * Instruments React's commit cycle to capture per-component render timing data.\n *\n * React exposes profiling data on fiber objects in development/profiling builds:\n * - `fiber.actualDuration` — wall-clock ms spent rendering this fiber + descendants\n * - `fiber.selfBaseDuration` — ms spent rendering just this fiber (excl. children)\n * - `fiber.actualStartTime` — performance.now() timestamp when render began\n *\n * We hook into `onCommitFiberRoot` on the DevTools hook to intercept every\n * commit, walk the work-in-progress subtree, and accumulate counts + durations\n * keyed by fiber identity.\n */\n\nimport type { ScopeDevToolsHook } from \"./devtools-hook.js\";\nimport type { Fiber } from \"./fiber-walker.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Profiling record stored per fiber. */\ninterface ProfilingRecord {\n renderCount: number;\n renderDuration: number;\n}\n\n/** Public snapshot returned by `getProfilingData`. */\nexport interface ProfilingSnapshot {\n renderCount: number;\n renderDuration: number;\n}\n\n// ---------------------------------------------------------------------------\n// Internal state\n// ---------------------------------------------------------------------------\n\n/**\n * Map from fiber numeric ID → profiling record.\n *\n * We key by `fiber._debugID` when present, falling back to the object\n * reference itself stored in `_fiberRefMap`.\n */\nconst _profilingData = new Map<number, ProfilingRecord>();\n\n/**\n * Secondary map for fibers that lack `_debugID`.\n * Maps the fiber object → a synthetic numeric key so we still accumulate\n * data across commits for the same fiber.\n */\nconst _fiberRefMap = new WeakMap<object, number>();\n\n/** Counter for synthetic IDs assigned to fibers without `_debugID`. */\nlet _syntheticIdCounter = -1;\n\n/** Whether the profiler has been installed on a hook. */\nlet _installed = false;\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Derive a stable numeric key for a fiber.\n *\n * React assigns `_debugID` in development builds (>=16). In environments\n * where it's absent we mint a synthetic negative integer so it never collides\n * with React's positive IDs.\n */\nfunction fiberId(fiber: Fiber): number {\n if (typeof fiber._debugID === \"number\") {\n return fiber._debugID;\n }\n // Use the fiber object itself as a WeakMap key\n const existing = _fiberRefMap.get(fiber);\n if (existing !== undefined) return existing;\n const id = _syntheticIdCounter--;\n _fiberRefMap.set(fiber, id);\n return id;\n}\n\n/**\n * Walk an alternate (work-in-progress) fiber subtree and accumulate profiling\n * data for every node that has `actualDuration` set (i.e. was actually\n * rendered in this commit).\n *\n * React sets `actualDuration === -1` (or leaves it unset) for fibers that\n * were bailed out of rendering — we skip those.\n *\n * We walk via `child` + `sibling` rather than relying on the `return` pointer\n * so we stay within the committed subtree.\n */\nfunction walkCommittedFibers(fiber: Fiber | null): void {\n if (fiber === null || fiber === undefined) return;\n\n const actualDuration: number =\n typeof fiber.actualDuration === \"number\" ? fiber.actualDuration : -1;\n const selfBaseDuration: number =\n typeof fiber.selfBaseDuration === \"number\" ? fiber.selfBaseDuration : 0;\n\n // A non-negative actualDuration means this fiber was rendered in this commit\n if (actualDuration >= 0) {\n const id = fiberId(fiber);\n const existing = _profilingData.get(id);\n if (existing !== undefined) {\n existing.renderCount += 1;\n // Accumulate self (not total) duration so parent durations don't double-count\n existing.renderDuration += selfBaseDuration;\n } else {\n _profilingData.set(id, {\n renderCount: 1,\n renderDuration: selfBaseDuration,\n });\n }\n }\n\n // Recurse into children and siblings\n walkCommittedFibers(fiber.child ?? null);\n walkCommittedFibers(fiber.sibling ?? null);\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Install the profiler onto a DevTools hook.\n *\n * Wraps `hook.onCommitFiberRoot` so that every React commit triggers a walk\n * of the committed fiber subtree to accumulate profiling data.\n *\n * Safe to call multiple times — subsequent calls on the same hook are no-ops.\n */\nexport function installProfiler(hook: ScopeDevToolsHook): void {\n if (_installed) return;\n _installed = true;\n\n const originalOnCommit = hook.onCommitFiberRoot.bind(hook);\n\n hook.onCommitFiberRoot = (\n rendererID: number,\n // biome-ignore lint/suspicious/noExplicitAny: React DevTools hook signature\n root: any,\n priorityLevel: unknown,\n ): void => {\n // Call the original handler first so fiber roots are tracked\n originalOnCommit(rendererID, root, priorityLevel);\n\n // Walk the work-in-progress (alternate) fiber tree for profiling data.\n // `root.current` is the current committed tree; `root.current.alternate`\n // is the work-in-progress tree that was just committed.\n const wipRoot: Fiber | null = root?.current?.alternate ?? root?.current ?? null;\n if (wipRoot !== null) {\n walkCommittedFibers(wipRoot);\n }\n };\n}\n\n/**\n * Retrieve the accumulated profiling snapshot for a fiber by its numeric ID.\n *\n * @param fiberId - The fiber's `_debugID` (or synthetic ID assigned by this module).\n * @returns `{ renderCount, renderDuration }` if data exists, `null` otherwise.\n */\nexport function getProfilingData(fiberIdParam: number): ProfilingSnapshot | null {\n const record = _profilingData.get(fiberIdParam);\n if (record === undefined) return null;\n return { renderCount: record.renderCount, renderDuration: record.renderDuration };\n}\n\n/**\n * Reset all accumulated profiling data and the installed state.\n *\n * Primarily used in tests and when re-initialising the capture session.\n * Note: this does NOT restore the original `onCommitFiberRoot` handler —\n * call `installProfiler` again on a fresh hook after resetting.\n */\nexport function resetProfilingData(): void {\n _profilingData.clear();\n _installed = false;\n _syntheticIdCounter = -1;\n // WeakMap entries are GC'd automatically; no need to clear _fiberRefMap\n}\n\n/**\n * @internal\n * Expose the raw data map for testing purposes.\n */\nexport function _getProfilingDataMap(): Map<number, ProfilingRecord> {\n return _profilingData;\n}\n","/**\n * fiber-walker.ts\n *\n * Traverses a React fiber tree and converts it into the `ComponentNode` tree\n * defined in `@agent-scope/core`.\n *\n * Fiber internals are undocumented React implementation details. We rely on:\n * - `fiber.tag` — type classifier (see FIBER_TAGS below)\n * - `fiber.type` — function/class reference or string for host elements\n * - `fiber.memoizedProps` — current props snapshot\n * - `fiber.child` — first child fiber\n * - `fiber.sibling` — next sibling fiber\n * - `fiber._debugSource` — source location injected by babel (dev only)\n * - `fiber._debugID` — internal numeric ID (dev only, may be absent)\n * - `fiber.index` — position among siblings\n */\n\nimport type { ComponentNode, ComponentType, SourceLocation } from \"@agent-scope/core\";\nimport { serialize } from \"@agent-scope/core\";\nimport { extractContextConsumptions } from \"./context-extractor.js\";\nimport { extractHooks } from \"./hooks-extractor.js\";\nimport { getProfilingData } from \"./profiler.js\";\n\n// ---------------------------------------------------------------------------\n// Fiber tag constants (React source: ReactWorkTags.js)\n// ---------------------------------------------------------------------------\n\nconst FunctionComponent = 0;\nconst ClassComponent = 1;\nconst IndeterminateComponent = 2;\nconst HostRoot = 3;\n// HostPortal = 4 (not used for node extraction)\nconst HostComponent = 5;\nconst HostText = 6;\nconst Fragment = 7;\n// Mode = 8 (StrictMode etc.)\n// ContextConsumer = 9\n// ContextProvider = 10\nconst ForwardRef = 11;\n// Profiler = 12\nconst SuspenseComponent = 13;\nconst MemoComponent = 14;\nconst SimpleMemoComponent = 15;\n// LazyComponent = 16\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal shape of a React fiber as accessed by this walker.\n * Only the fields we actually read are declared here.\n */\nexport interface Fiber {\n tag: number;\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n type: any;\n // biome-ignore lint/suspicious/noExplicitAny: arbitrary props\n memoizedProps: Record<string, any> | null;\n child: Fiber | null;\n sibling: Fiber | null;\n return: Fiber | null;\n /** Present in React dev builds (>=16). Numeric per-session fiber ID. */\n _debugID?: number;\n /** Position among siblings (0-based). Used as fallback ID. */\n index: number;\n /** Injected by `babel-plugin-transform-react-jsx-source` (dev only). */\n _debugSource?: {\n fileName: string;\n lineNumber: number;\n columnNumber: number;\n } | null;\n // biome-ignore lint/suspicious/noExplicitAny: arbitrary\n [key: string]: any;\n}\n\nexport interface WalkOptions {\n /**\n * When `true`, host elements (div, span, etc.) are included in the output.\n * Default: `false`.\n */\n includeHostElements?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Sequential ID generator\n// ---------------------------------------------------------------------------\n\nlet _idCounter = 1;\n\n/** Reset the ID counter. Used in unit tests only. */\nexport function _resetIdCounter(): void {\n _idCounter = 1;\n}\n\nfunction nextId(): number {\n return _idCounter++;\n}\n\n// ---------------------------------------------------------------------------\n// Name extraction helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Property key names that JS engines infer automatically from object\n * literals, which we must NOT treat as user-supplied display names.\n *\n * e.g. `{ render: () => null }.render.name === \"render\"` due to inferred names.\n */\nconst INFERRED_PROPERTY_NAMES = new Set([\"render\", \"type\", \"forward_ref\", \"memo\"]);\n\nfunction isUserSuppliedName(name: unknown, tag: number): boolean {\n if (typeof name !== \"string\" || !name) return false;\n // For ForwardRef/Memo wrappers the inner function name is sometimes inferred\n // from the property key (\"render\" or \"type\"). Treat those as anonymous.\n if (\n (tag === ForwardRef || tag === MemoComponent || tag === SimpleMemoComponent) &&\n INFERRED_PROPERTY_NAMES.has(name)\n ) {\n return false;\n }\n return true;\n}\n\n/**\n * Derive the display name from a fiber's `type` field.\n *\n * Resolution order:\n * 1. `type.displayName`\n * 2. `type.name` (function/class name — unless inferred from a property key)\n * 3. For forwardRef wrappers: inner `render.displayName` / `render.name`\n * 4. For memo wrappers: inner `type.displayName` / `type.name`\n * 5. String tags for host elements (\"div\", \"span\", …)\n * 6. Fallback: \"Anonymous\"\n */\nexport function extractName(fiber: Fiber): string {\n const { type, tag } = fiber;\n\n if (type === null || type === undefined) {\n if (tag === HostRoot) return \"HostRoot\";\n if (tag === Fragment) return \"Fragment\";\n if (tag === HostText) return \"#text\";\n return \"Anonymous\";\n }\n\n // String type = host element\n if (typeof type === \"string\") {\n return type;\n }\n\n // Direct displayName (always preferred — user explicitly set this)\n if (typeof type.displayName === \"string\" && type.displayName) {\n return type.displayName;\n }\n\n // ForwardRef — React wraps the component in an object with `render`\n if (tag === ForwardRef || (type.$$typeof && String(type.$$typeof).includes(\"forward_ref\"))) {\n const render = type.render;\n if (render) {\n if (typeof render.displayName === \"string\" && render.displayName) return render.displayName;\n if (isUserSuppliedName(render.name, tag)) return render.name as string;\n }\n return \"ForwardRef\";\n }\n\n // Memo — React wraps in an object with `type`\n if (\n tag === MemoComponent ||\n tag === SimpleMemoComponent ||\n (type.$$typeof && String(type.$$typeof).includes(\"memo\"))\n ) {\n const inner = type.type;\n if (inner) {\n if (typeof inner.displayName === \"string\" && inner.displayName) return inner.displayName;\n if (isUserSuppliedName(inner.name, tag)) return inner.name as string;\n }\n return \"Memo\";\n }\n\n // Standard function/class name\n if (isUserSuppliedName(type.name, tag)) {\n return type.name as string;\n }\n\n return \"Anonymous\";\n}\n\n// ---------------------------------------------------------------------------\n// Component type classification\n// ---------------------------------------------------------------------------\n\n/**\n * Map a fiber tag (and optionally the `type` object's `$$typeof`) to one of\n * our `ComponentType` discriminants.\n */\nexport function classifyType(fiber: Fiber): ComponentType {\n const { tag, type } = fiber;\n\n switch (tag) {\n case FunctionComponent:\n case IndeterminateComponent:\n return \"function\";\n\n case ClassComponent:\n return \"class\";\n\n case ForwardRef:\n return \"forward_ref\";\n\n case MemoComponent:\n case SimpleMemoComponent:\n return \"memo\";\n\n case HostComponent:\n case HostText:\n return \"host\";\n\n default:\n // For tags we don't explicitly map, inspect `$$typeof` if present\n if (type && typeof type === \"object\") {\n const typeofStr = String(type.$$typeof ?? \"\");\n if (typeofStr.includes(\"forward_ref\")) return \"forward_ref\";\n if (typeofStr.includes(\"memo\")) return \"memo\";\n }\n return \"function\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Source location extraction\n// ---------------------------------------------------------------------------\n\nfunction extractSource(fiber: Fiber): SourceLocation | null {\n // Standard babel-plugin-transform-react-jsx-source injects _debugSource\n if (fiber._debugSource) {\n const { fileName, lineNumber, columnNumber } = fiber._debugSource;\n return {\n fileName: String(fileName),\n lineNumber: Number(lineNumber),\n columnNumber: Number(columnNumber),\n };\n }\n\n // Our babel plugin might inject __scopeSource into memoizedProps\n const scopeSource = fiber.memoizedProps?.__scopeSource;\n if (scopeSource && typeof scopeSource === \"object\") {\n const { fileName, lineNumber, columnNumber } = scopeSource as {\n fileName: unknown;\n lineNumber: unknown;\n columnNumber: unknown;\n };\n if (\n typeof fileName === \"string\" &&\n typeof lineNumber === \"number\" &&\n typeof columnNumber === \"number\"\n ) {\n return { fileName, lineNumber, columnNumber };\n }\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Skip predicate\n// ---------------------------------------------------------------------------\n\n/**\n * Return `true` for fibers we should not emit as `ComponentNode`s.\n *\n * We always skip:\n * - HostRoot (internal React root container)\n * - HostText (raw text nodes)\n * - Fragment, SuspenseComponent wrappers\n *\n * We conditionally skip:\n * - HostComponent (\"div\", \"span\", …) — controlled by `includeHostElements`\n */\nfunction shouldSkip(fiber: Fiber, includeHost: boolean): boolean {\n const { tag } = fiber;\n\n // Always skip internal bookkeeping nodes\n if (tag === HostRoot || tag === HostText || tag === Fragment || tag === SuspenseComponent) {\n return true;\n }\n\n // Host elements: skip by default\n if (tag === HostComponent && !includeHost) {\n return true;\n }\n\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Core walker\n// ---------------------------------------------------------------------------\n\n/**\n * Walk a fiber and all its descendants, collecting `ComponentNode`s.\n *\n * @param rootFiber - The starting fiber.\n * @param options - Walk configuration.\n * @returns The `ComponentNode` for `rootFiber`, or `null` if the root should\n * be skipped. Children are populated recursively.\n */\nexport function walkFiber(fiber: Fiber | null, options: WalkOptions = {}): ComponentNode | null {\n if (fiber === null || fiber === undefined) return null;\n\n const includeHost = options.includeHostElements ?? false;\n return walkFiberInner(fiber, includeHost, new Set<Fiber>());\n}\n\nfunction walkFiberInner(\n fiber: Fiber | null | undefined,\n includeHost: boolean,\n visited: Set<Fiber>,\n): ComponentNode | null {\n if (fiber === null || fiber === undefined) return null;\n\n // Cycle guard — should not happen in a healthy fiber tree\n if (visited.has(fiber)) return null;\n\n // Check skip BEFORE adding to visited so that the transparent-skip path in\n // collectChildren can still promote this fiber's children.\n if (shouldSkip(fiber, includeHost)) {\n return null;\n }\n\n visited.add(fiber);\n\n // Assign ID first (parent before children) for predictable sequential IDs\n const id = typeof fiber._debugID === \"number\" ? fiber._debugID : nextId();\n const profilingData = getProfilingData(id);\n\n // Collect child nodes by walking child + sibling chains\n const children: ComponentNode[] = collectChildren(fiber, includeHost, visited);\n\n const node: ComponentNode = {\n id,\n name: extractName(fiber),\n type: classifyType(fiber),\n source: extractSource(fiber),\n props: serialize(fiber.memoizedProps ?? {}),\n state: extractHooks(fiber),\n context: extractContextConsumptions(fiber),\n renderCount: profilingData?.renderCount ?? 1,\n renderDuration: profilingData?.renderDuration ?? 0,\n children,\n };\n\n return node;\n}\n\n/**\n * Collect the `ComponentNode` children of a fiber by walking its `child`\n * fiber and then all subsequent `sibling` fibers.\n *\n * Skipped fibers are transparent — their own children are promoted up.\n */\nfunction collectChildren(fiber: Fiber, includeHost: boolean, visited: Set<Fiber>): ComponentNode[] {\n const nodes: ComponentNode[] = [];\n let current: Fiber | null = fiber.child ?? null;\n\n while (current !== null) {\n if (visited.has(current)) {\n current = current.sibling ?? null;\n continue;\n }\n\n if (shouldSkip(current, includeHost)) {\n // Transparent skip: this node is invisible, promote its children upward.\n // We do NOT add to visited here so that cycle guard still works correctly\n // if the same skipped node appears elsewhere (which shouldn't happen in\n // practice, but defensively correct).\n const promoted = collectChildren(current, includeHost, visited);\n nodes.push(...promoted);\n } else {\n const node = walkFiberInner(current, includeHost, visited);\n if (node !== null) {\n nodes.push(node);\n }\n }\n\n current = current.sibling ?? null;\n }\n\n return nodes;\n}\n\n// ---------------------------------------------------------------------------\n// Walk from a fiber root object (as returned by DevTools hook)\n// ---------------------------------------------------------------------------\n\n/**\n * Walk a fiber root (the object stored in `ReactRenderer.fiberRoots`) and\n * return the root `ComponentNode`, or `null` if the tree is empty.\n *\n * `fiberRoot.current` is the `HostRoot` fiber — we skip it and return the\n * first meaningful child.\n */\n// biome-ignore lint/suspicious/noExplicitAny: React DevTools fiber root shape\nexport function walkFiberRoot(fiberRoot: any, options: WalkOptions = {}): ComponentNode | null {\n if (!fiberRoot) return null;\n\n const hostRootFiber: Fiber | null = fiberRoot.current ?? null;\n if (!hostRootFiber) return null;\n\n const includeHost = options.includeHostElements ?? false;\n const visited = new Set<Fiber>();\n\n // The HostRoot itself is skipped. Collect its children directly.\n const children = collectChildren(hostRootFiber, includeHost, visited);\n\n if (children.length === 0) return null;\n if (children.length === 1) return children[0] ?? null;\n\n // Multiple root children (rare) — synthesise a wrapper\n return {\n id: nextId(),\n name: \"Root\",\n type: \"function\",\n source: null,\n props: serialize({}),\n state: [],\n context: [],\n renderCount: 1,\n renderDuration: 0,\n children,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Lightweight walker\n// ---------------------------------------------------------------------------\n\nimport type { HookType, LightweightComponentNode } from \"@agent-scope/core\";\n\n// ---------------------------------------------------------------------------\n// Hook counting/classification helpers (no value serialization)\n// ---------------------------------------------------------------------------\n\n/** Minimal interface for a hook linked-list node (lightweight path). */\ninterface LightweightHookNode {\n memoizedState: unknown;\n // biome-ignore lint/suspicious/noExplicitAny: React update queue internals\n queue: Record<string, any> | null | undefined;\n next: LightweightHookNode | null;\n}\n\nconst HookLayout = 0b00100; // 4 — useLayoutEffect flag\n\nfunction isLightweightEffectNode(node: LightweightHookNode): boolean {\n const ms = node.memoizedState;\n if (ms === null || typeof ms !== \"object\") return false;\n const obj = ms as Record<string, unknown>;\n return typeof obj.create === \"function\" && \"deps\" in obj && typeof obj.tag === \"number\";\n}\n\nfunction isLightweightRefNode(node: LightweightHookNode): boolean {\n if (node.queue != null) return false;\n const ms = node.memoizedState;\n if (ms === null || typeof ms !== \"object\" || Array.isArray(ms)) return false;\n const keys = Object.keys(ms as object);\n return keys.length === 1 && keys[0] === \"current\";\n}\n\nfunction isLightweightMemoTuple(node: LightweightHookNode): boolean {\n if (node.queue != null) return false;\n const ms = node.memoizedState;\n if (!Array.isArray(ms) || ms.length !== 2) return false;\n return ms[1] === null || Array.isArray(ms[1]);\n}\n\nfunction isLightweightStateOrReducer(node: LightweightHookNode): boolean {\n return (\n node.queue != null &&\n typeof node.queue === \"object\" &&\n typeof node.queue.dispatch === \"function\"\n );\n}\n\nfunction isLightweightReducer(node: LightweightHookNode): boolean {\n if (!isLightweightStateOrReducer(node)) return false;\n const q = node.queue as Record<string, unknown>;\n if (typeof q.reducer === \"function\") return true;\n const lrr = q.lastRenderedReducer;\n if (typeof lrr !== \"function\") return false;\n const name = (lrr as { name?: string }).name ?? \"\";\n return name !== \"basicStateReducer\" && name !== \"\";\n}\n\n/**\n * Classify a single hook node into a `HookType` without serializing its value.\n */\nfunction classifyHookType(node: LightweightHookNode): HookType {\n if (isLightweightEffectNode(node)) {\n const ms = node.memoizedState as { tag: number };\n return ms.tag & HookLayout ? \"useLayoutEffect\" : \"useEffect\";\n }\n if (isLightweightRefNode(node)) return \"useRef\";\n if (isLightweightMemoTuple(node)) {\n const [val] = node.memoizedState as [unknown, unknown];\n return typeof val === \"function\" ? \"useCallback\" : \"useMemo\";\n }\n if (isLightweightStateOrReducer(node)) {\n return isLightweightReducer(node) ? \"useReducer\" : \"useState\";\n }\n return \"custom\";\n}\n\n/**\n * Walk a fiber's memoizedState linked list and return hook count + types\n * WITHOUT serializing any hook values.\n */\nfunction countAndClassifyHooks(fiber: Fiber): { hookCount: number; hookTypes: HookType[] } {\n const hookTypes: HookType[] = [];\n // biome-ignore lint/suspicious/noExplicitAny: React fiber internals\n let node: LightweightHookNode | null = (fiber.memoizedState as any) ?? null;\n // memoizedState is only a hook list for function components; for class\n // components it holds instance state directly (not a linked list).\n // We guard by checking that the first node has a `next` key (hook nodes always do).\n if (node === null || typeof node !== \"object\" || !(\"next\" in (node as object))) {\n return { hookCount: 0, hookTypes: [] };\n }\n while (node !== null) {\n hookTypes.push(classifyHookType(node));\n node = node.next ?? null;\n }\n return { hookCount: hookTypes.length, hookTypes };\n}\n\n// ---------------------------------------------------------------------------\n// walkFiberLightweight — public API\n// ---------------------------------------------------------------------------\n\n/**\n * Walk a fiber and all its descendants, producing a `LightweightComponentNode`\n * tree. Props, state values, context, source, renderCount and renderDuration\n * are deliberately omitted — only structural / identification fields are\n * included.\n *\n * @param fiber - The starting fiber.\n * @param options - Walk configuration (same as `walkFiber`).\n * @returns The `LightweightComponentNode` for `fiber`, or `null` if it should\n * be skipped.\n */\nexport function walkFiberLightweight(\n fiber: Fiber | null,\n options: WalkOptions = {},\n): LightweightComponentNode | null {\n if (fiber === null || fiber === undefined) return null;\n const includeHost = options.includeHostElements ?? false;\n return walkFiberLightweightInner(fiber, includeHost, new Set<Fiber>(), 0);\n}\n\nfunction walkFiberLightweightInner(\n fiber: Fiber | null | undefined,\n includeHost: boolean,\n visited: Set<Fiber>,\n depth: number,\n): LightweightComponentNode | null {\n if (fiber === null || fiber === undefined) return null;\n if (visited.has(fiber)) return null;\n if (shouldSkip(fiber, includeHost)) return null;\n\n visited.add(fiber);\n\n const id = typeof fiber._debugID === \"number\" ? fiber._debugID : nextId();\n const { hookCount, hookTypes } = countAndClassifyHooks(fiber);\n const children = collectLightweightChildren(fiber, includeHost, visited, depth + 1);\n\n const node: LightweightComponentNode = {\n id,\n name: extractName(fiber),\n type: classifyType(fiber),\n hookCount,\n hookTypes,\n childCount: children.length,\n depth,\n children,\n };\n\n return node;\n}\n\nfunction collectLightweightChildren(\n fiber: Fiber,\n includeHost: boolean,\n visited: Set<Fiber>,\n childDepth: number,\n): LightweightComponentNode[] {\n const nodes: LightweightComponentNode[] = [];\n let current: Fiber | null = fiber.child ?? null;\n\n while (current !== null) {\n if (visited.has(current)) {\n current = current.sibling ?? null;\n continue;\n }\n\n if (shouldSkip(current, includeHost)) {\n // Transparent skip — promote children upward, keeping childDepth correct\n const promoted = collectLightweightChildren(current, includeHost, visited, childDepth);\n nodes.push(...promoted);\n } else {\n const node = walkFiberLightweightInner(current, includeHost, visited, childDepth);\n if (node !== null) {\n nodes.push(node);\n }\n }\n\n current = current.sibling ?? null;\n }\n\n return nodes;\n}\n\n// ---------------------------------------------------------------------------\n// walkFiberRootLightweight — walk from a fiber root object\n// ---------------------------------------------------------------------------\n\n/**\n * Walk a fiber root (as returned by the DevTools hook) and return the root\n * `LightweightComponentNode`, or `null` if the tree is empty.\n *\n * Mirrors `walkFiberRoot` but uses the lightweight walker.\n */\nexport function walkFiberRootLightweight(\n // biome-ignore lint/suspicious/noExplicitAny: React DevTools fiber root shape\n fiberRoot: any,\n options: WalkOptions = {},\n): LightweightComponentNode | null {\n if (!fiberRoot) return null;\n\n const hostRootFiber: Fiber | null = fiberRoot.current ?? null;\n if (!hostRootFiber) return null;\n\n const includeHost = options.includeHostElements ?? false;\n const visited = new Set<Fiber>();\n\n // The HostRoot itself is skipped — collect its children directly at depth 0.\n const children = collectLightweightChildren(hostRootFiber, includeHost, visited, 0);\n\n if (children.length === 0) return null;\n if (children.length === 1) return children[0] ?? null;\n\n // Multiple root children (rare) — synthesise a wrapper at depth -1 (its\n // children are already at depth 0, which is correct).\n return {\n id: nextId(),\n name: \"Root\",\n type: \"function\",\n hookCount: 0,\n hookTypes: [],\n childCount: children.length,\n depth: 0,\n children,\n };\n}\n","/**\n * suspense-detector.ts\n *\n * Detects `<Suspense>` boundaries in the fiber tree and determines their\n * current status at capture time.\n *\n * React stores Suspense state in the fiber's `memoizedState` field using an\n * internal linked-list structure. The first node in the list is the dehydrated\n * / retrying state object when the boundary is suspended.\n *\n * Status heuristics (based on React internals):\n *\n * resolved — `memoizedState === null`\n * The boundary rendered its normal children successfully.\n *\n * pending — `memoizedState.dehydrated` is set, OR the state object\n * contains a thenable (`then` function) anywhere at the top\n * level, indicating React is still waiting for data.\n *\n * fallback — `memoizedState` is non-null but does not look like a pending\n * thenable; the fallback subtree is being rendered. This covers\n * the case where the promise has been thrown but not yet\n * resolved, and React is showing the fallback UI.\n *\n * Note: these are approximations over undocumented internals. React does not\n * expose a public API for querying Suspense status from outside the component.\n */\n\nimport type { SuspenseBoundaryInfo } from \"@agent-scope/core\";\nimport type { Fiber } from \"./fiber-walker.js\";\n\n// ---------------------------------------------------------------------------\n// Fiber tag constants\n// ---------------------------------------------------------------------------\n\nconst SuspenseComponent = 13;\nconst HostText = 6;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extract a display name for the component that *contains* this Suspense\n * boundary, i.e. the nearest named ancestor.\n */\nfunction nearestAncestorName(fiber: Fiber): string {\n let current: Fiber | null = fiber.return ?? null;\n while (current !== null) {\n const { type } = current;\n if (type && typeof type !== \"string\") {\n const name: unknown =\n (type as { displayName?: unknown }).displayName ?? (type as { name?: unknown }).name;\n if (typeof name === \"string\" && name) return name;\n }\n current = current.return ?? null;\n }\n return \"Unknown\";\n}\n\n/**\n * Determine the name of the fallback element (if identifiable).\n *\n * The fallback is the *second* child of a Suspense fiber — React renders the\n * primary child tree first, then attaches the fallback as a sibling. When\n * suspended, the primary tree is hidden and the fallback is shown.\n *\n * Returns `null` when the fallback is a plain text node or not identifiable.\n */\nfunction extractFallbackName(fiber: Fiber): string | null {\n // The fallback is typically the second child of the Suspense fiber\n const primary = fiber.child ?? null;\n const fallback = primary?.sibling ?? null;\n if (!fallback) return null;\n\n const { type, tag } = fallback;\n if (tag === HostText) return null;\n if (typeof type === \"string\") return type; // host element, e.g. \"div\"\n if (type && typeof type.displayName === \"string\" && type.displayName) return type.displayName;\n if (type && typeof type.name === \"string\" && type.name) return type.name;\n return null;\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: React fiber internals are untyped\ntype SuspenseMemoizedState = any;\n\n/**\n * Classify the Suspense boundary status from `memoizedState`.\n *\n * - `null` → resolved (primary content visible)\n * - dehydrated → pending (SSR dehydrated boundary, not yet hydrated)\n * - has thenable → pending (a Promise was thrown, still in-flight)\n * - non-null → fallback (suspended, showing fallback UI)\n */\nfunction classifyStatus(memoizedState: SuspenseMemoizedState): SuspenseBoundaryInfo[\"isSuspended\"] {\n if (memoizedState === null || memoizedState === undefined) {\n // resolved\n return false;\n }\n\n // Dehydrated SSR boundary\n if (\n typeof memoizedState === \"object\" &&\n memoizedState.dehydrated !== undefined &&\n memoizedState.dehydrated !== null\n ) {\n return true; // pending\n }\n\n // Thenable at top level of state object (React stores the thrown promise)\n if (typeof memoizedState === \"object\" && typeof memoizedState.then === \"function\") {\n return true; // pending\n }\n\n // Non-null state but no thenable → fallback is being shown\n return true; // fallback / suspended\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Walk the fiber tree and collect `SuspenseBoundaryInfo` for every\n * `<Suspense>` boundary found.\n *\n * @param rootFiber - Starting fiber (typically the HostRoot's first child).\n * @returns Flat list of Suspense boundary descriptors.\n */\nexport function detectSuspenseBoundaries(rootFiber: Fiber | null): SuspenseBoundaryInfo[] {\n const results: SuspenseBoundaryInfo[] = [];\n const visited = new Set<Fiber>();\n\n function walk(fiber: Fiber | null): void {\n if (fiber === null || fiber === undefined) return;\n if (visited.has(fiber)) return;\n visited.add(fiber);\n\n if (fiber.tag === SuspenseComponent) {\n const isSuspended = classifyStatus(fiber.memoizedState);\n const componentName = nearestAncestorName(fiber);\n const fallbackName = extractFallbackName(fiber);\n\n // Use _debugID when available for a stable ID, otherwise fall back to\n // the fiber's index within its parent\n const id: number = typeof fiber._debugID === \"number\" ? fiber._debugID : fiber.index;\n\n results.push({\n id,\n componentName,\n isSuspended,\n suspendedDuration: null, // timing not available at capture time\n fallbackName,\n source: fiber._debugSource\n ? {\n fileName: String(fiber._debugSource.fileName),\n lineNumber: Number(fiber._debugSource.lineNumber),\n columnNumber: Number(fiber._debugSource.columnNumber),\n }\n : null,\n });\n }\n\n walk(fiber.child ?? null);\n walk(fiber.sibling ?? null);\n }\n\n walk(rootFiber);\n return results;\n}\n","/**\n * capture.ts\n *\n * High-level `capture()` function — wires together the DevTools hook and fiber\n * walker to produce a partial `PageReport`.\n */\n\nimport type {\n CapturedError,\n LightweightComponentNode,\n PageReport,\n SuspenseBoundaryInfo,\n} from \"@agent-scope/core\";\nimport {\n clearConsoleEntries,\n getConsoleEntries,\n installConsoleInterceptor,\n uninstallConsoleInterceptor,\n} from \"./console-interceptor.js\";\nimport { getHook, installHook, waitForReact } from \"./devtools-hook.js\";\nimport { detectErrors } from \"./error-detector.js\";\nimport type { WalkOptions } from \"./fiber-walker.js\";\nimport { walkFiberRoot, walkFiberRootLightweight } from \"./fiber-walker.js\";\nimport { installProfiler } from \"./profiler.js\";\nimport { detectSuspenseBoundaries } from \"./suspense-detector.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface CaptureOptions extends WalkOptions {\n /**\n * URL to record in the report.\n * Defaults to `window.location.href` in a browser context.\n */\n url?: string;\n /**\n * Timeout in milliseconds to wait for React to boot before giving up.\n * Default: 10 000.\n */\n reactTimeout?: number;\n /**\n * When `true`, perform a lightweight capture that omits props, state,\n * context, source, renderCount, and renderDuration.\n *\n * Produces a `LightweightCaptureResult` instead of a full `CaptureResult`.\n * Expected size reduction: ~99% (e.g. 300 MB → ~3 MB for 2 500 nodes).\n *\n * Default: `false`.\n */\n lightweight?: boolean;\n}\n\n/** The fields populated by a full `capture()`. */\nexport type CaptureResult = Pick<\n PageReport,\n \"url\" | \"timestamp\" | \"capturedIn\" | \"tree\" | \"consoleEntries\" | \"errors\" | \"suspenseBoundaries\"\n>;\n\n/** The fields populated by a lightweight `capture({ lightweight: true })`. */\nexport interface LightweightCaptureResult {\n url: string;\n timestamp: number;\n capturedIn: number;\n tree: LightweightComponentNode;\n consoleEntries: PageReport[\"consoleEntries\"];\n errors: CapturedError[];\n suspenseBoundaries: SuspenseBoundaryInfo[];\n}\n\n// ---------------------------------------------------------------------------\n// capture()\n// ---------------------------------------------------------------------------\n\n/**\n * Capture a snapshot of the current React component tree.\n *\n * Ensures the DevTools hook is installed, waits for React to register a\n * renderer (if it hasn't already), then walks the first available fiber root.\n *\n * Console messages emitted during the capture window are recorded via the\n * console interceptor and included in the returned `consoleEntries` field.\n *\n * Also detects error boundaries that have caught errors and Suspense\n * boundaries with their current suspension status.\n *\n * @param options.lightweight - When `true`, returns a `LightweightCaptureResult`\n * with a minimal tree (no props/state/context/source/renderCount/renderDuration).\n *\n * @returns A `CaptureResult` (or `LightweightCaptureResult` when lightweight is\n * true) containing `url`, `timestamp`, `capturedIn`, `tree`,\n * `consoleEntries`, `errors`, and `suspenseBoundaries`.\n * @throws If no React renderer registers within `reactTimeout` ms, or if the\n * fiber tree is empty.\n */\nexport async function capture(\n options: CaptureOptions & { lightweight: true },\n): Promise<LightweightCaptureResult>;\nexport async function capture(options?: CaptureOptions): Promise<CaptureResult>;\nexport async function capture(\n options: CaptureOptions = {},\n): Promise<CaptureResult | LightweightCaptureResult> {\n const startTime = Date.now();\n\n // Ensure the hook is installed and profiler is wired\n const hook = installHook();\n installProfiler(hook);\n\n // Install console interceptor and start fresh\n installConsoleInterceptor();\n clearConsoleEntries();\n\n // Resolve the URL\n const url = options.url ?? (typeof window !== \"undefined\" ? window.location.href : \"unknown\");\n\n try {\n // Wait for a renderer\n const renderer = await waitForReact(options.reactTimeout ?? 10_000);\n\n // Grab the first fiber root from the renderer\n const fiberRoot = Array.from(renderer.fiberRoots)[0] ?? null;\n\n if (!fiberRoot) {\n throw new Error(\n \"capture(): React renderer registered but no fiber roots found. \" +\n \"Make sure React has rendered at least one component.\",\n );\n }\n\n const walkOptions: WalkOptions = {\n includeHostElements: options.includeHostElements ?? false,\n };\n\n // The HostRoot fiber is fiberRoot.current; walk from its first child for\n // error/suspense detection so we cover the same subtree as the walkers.\n const hostRootFiber = fiberRoot.current ?? null;\n const rootChild = hostRootFiber?.child ?? null;\n\n const errors: CapturedError[] = detectErrors(rootChild);\n const suspenseBoundaries: SuspenseBoundaryInfo[] = detectSuspenseBoundaries(rootChild);\n const capturedIn = Date.now() - startTime;\n const consoleEntries = getConsoleEntries();\n\n if (options.lightweight) {\n const tree = walkFiberRootLightweight(fiberRoot, walkOptions);\n\n if (!tree) {\n throw new Error(\n \"capture(): Fiber tree is empty. \" +\n \"Make sure React has rendered at least one component.\",\n );\n }\n\n return {\n url,\n timestamp: startTime,\n capturedIn,\n tree,\n consoleEntries,\n errors,\n suspenseBoundaries,\n };\n }\n\n const tree = walkFiberRoot(fiberRoot, walkOptions);\n\n if (!tree) {\n throw new Error(\n \"capture(): Fiber tree is empty. \" + \"Make sure React has rendered at least one component.\",\n );\n }\n\n return {\n url,\n timestamp: startTime,\n capturedIn,\n tree,\n consoleEntries,\n errors,\n suspenseBoundaries,\n };\n } finally {\n // Always uninstall the interceptor to restore the original console\n uninstallConsoleInterceptor();\n }\n}\n\n// ---------------------------------------------------------------------------\n// installHook re-export (convenience)\n// ---------------------------------------------------------------------------\nexport { installHook, getHook };\n","/**\n * @agent-scope/runtime\n *\n * Browser instrumentation — captures React component trees at runtime.\n * Depends on @agent-scope/core for types.\n *\n * @packageDocumentation\n */\n\n// ---------------------------------------------------------------------------\n// Re-export shared types from @agent-scope/core\n// ---------------------------------------------------------------------------\nexport type {\n CapturedError,\n ComponentNode,\n LightweightComponentNode,\n PageReport,\n SuspenseBoundaryInfo,\n} from \"@agent-scope/core\";\nexport type { CaptureOptions, CaptureResult, LightweightCaptureResult } from \"./capture.js\";\n// ---------------------------------------------------------------------------\n// Capture\n// ---------------------------------------------------------------------------\nexport { capture } from \"./capture.js\";\n// ---------------------------------------------------------------------------\n// Console interceptor\n// ---------------------------------------------------------------------------\nexport {\n clearConsoleEntries,\n getConsoleEntries,\n installConsoleInterceptor,\n uninstallConsoleInterceptor,\n} from \"./console-interceptor.js\";\nexport type { ReactRenderer, ScopeDevToolsHook } from \"./devtools-hook.js\";\n// ---------------------------------------------------------------------------\n// DevTools hook\n// ---------------------------------------------------------------------------\nexport {\n getHook,\n getRenderers,\n installHook,\n waitForReact,\n} from \"./devtools-hook.js\";\n// ---------------------------------------------------------------------------\n// Error detection\n// ---------------------------------------------------------------------------\nexport { detectErrors } from \"./error-detector.js\";\nexport type { Fiber, WalkOptions } from \"./fiber-walker.js\";\n// ---------------------------------------------------------------------------\n// Fiber walker\n// ---------------------------------------------------------------------------\nexport {\n classifyType,\n extractName,\n walkFiber,\n walkFiberLightweight,\n walkFiberRoot,\n walkFiberRootLightweight,\n} from \"./fiber-walker.js\";\n// ---------------------------------------------------------------------------\n// Hooks extractor\n// ---------------------------------------------------------------------------\nexport { extractHooks } from \"./hooks-extractor.js\";\n// ---------------------------------------------------------------------------\n// Profiler\n// ---------------------------------------------------------------------------\nexport type { ProfilingSnapshot } from \"./profiler.js\";\nexport {\n getProfilingData,\n installProfiler,\n resetProfilingData,\n} from \"./profiler.js\";\n// ---------------------------------------------------------------------------\n// Suspense detection\n// ---------------------------------------------------------------------------\nexport { detectSuspenseBoundaries } from \"./suspense-detector.js\";\n\n// ---------------------------------------------------------------------------\n// Legacy ScopeRuntime class (stub compatibility shim)\n// ---------------------------------------------------------------------------\n\nimport type { ComponentNode, PageReport } from \"@agent-scope/core\";\n\n/** Options for initializing the Scope runtime */\nexport interface RuntimeOptions {\n /** Called whenever a new PageReport is captured */\n onCapture?: (report: PageReport) => void;\n /** Maximum number of reports to buffer before evicting the oldest */\n bufferSize?: number;\n}\n\n/** Manages an active capture session */\nexport class ScopeRuntime {\n private readonly buffer: PageReport[] = [];\n private readonly options: Required<Pick<RuntimeOptions, \"bufferSize\">> &\n Pick<RuntimeOptions, \"onCapture\">;\n\n constructor(options: RuntimeOptions = {}) {\n this.options = {\n bufferSize: options.bufferSize ?? 100,\n onCapture: options.onCapture,\n };\n }\n\n /** Record a captured PageReport */\n record(report: PageReport): void {\n if (this.buffer.length >= this.options.bufferSize) {\n this.buffer.shift();\n }\n this.buffer.push(report);\n this.options.onCapture?.(report);\n }\n\n /** Return all buffered reports and clear the buffer */\n flush(): PageReport[] {\n return this.buffer.splice(0);\n }\n\n /** Return a read-only snapshot of the buffer */\n getBuffer(): readonly PageReport[] {\n return this.buffer;\n }\n\n /** Find a node by fiber ID within a component tree */\n static findNode(root: ComponentNode, id: number): ComponentNode | null {\n if (root.id === id) return root;\n for (const child of root.children) {\n const found = ScopeRuntime.findNode(child, id);\n if (found !== null) return found;\n }\n return null;\n }\n}\n\n/** Create and return a new ScopeRuntime instance */\nexport function createRuntime(options?: RuntimeOptions): ScopeRuntime {\n return new ScopeRuntime(options);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-scope/runtime",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Browser instrumentation for Scope — captures React render events",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -29,7 +29,7 @@
29
29
  "clean": "rm -rf dist"
30
30
  },
31
31
  "dependencies": {
32
- "@agent-scope/core": "1.1.0"
32
+ "@agent-scope/core": "1.3.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "tsup": "*",