agent-react-devtools 0.2.2 → 0.3.0-canary-20260212081524

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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # agent-react-devtools
2
2
 
3
+ ## 0.3.0-canary-20260212081524
4
+
5
+ ### Minor Changes
6
+
7
+ - 20ce273: Standardize component reference format across all CLI output
8
+
9
+ All formatters now produce consistent `@cN [type] Name` references. Previously, tree and search commands used `@c1 [fn] "Name"` while profiling commands omitted labels, type tags, or both.
10
+
11
+ **Breaking changes to output format:**
12
+
13
+ - Component names are no longer quoted: `@c1 [fn] App` instead of `@c1 [fn] "App"`
14
+ - Keys use `key=value` instead of `key="value"`
15
+ - Profiling commands (`profile slow`, `profile rerenders`, `profile stop`, `profile commit`) now include `@cN` labels and `[type]` tags
16
+ - `profile slow` and `profile rerenders` show all render causes instead of only the first
17
+ - `profile report` now includes a `[type]` tag in the header
18
+ - Column-aligned padding removed from profiling output in favor of consistent `formatRef` formatting
19
+
3
20
  ## 0.2.2
4
21
 
5
22
  ### Patch Changes
package/README.md CHANGED
@@ -44,15 +44,15 @@ agent-react-devtools get tree --depth 3
44
44
  ```
45
45
 
46
46
  ```
47
- @c1 [fn] "App"
48
- ├─ @c2 [fn] "Header"
49
- │ ├─ @c3 [fn] "Nav"
50
- │ └─ @c4 [fn] "SearchBar"
51
- ├─ @c5 [fn] "TodoList"
52
- │ ├─ @c6 [fn] "TodoItem" key="1"
53
- │ ├─ @c7 [fn] "TodoItem" key="2"
54
- │ └─ @c8 [fn] "TodoItem" key="3"
55
- └─ @c9 [fn] "Footer"
47
+ @c1 [fn] App
48
+ ├─ @c2 [fn] Header
49
+ │ ├─ @c3 [fn] Nav
50
+ │ └─ @c4 [fn] SearchBar
51
+ ├─ @c5 [fn] TodoList
52
+ │ ├─ @c6 [fn] TodoItem key=1
53
+ │ ├─ @c7 [fn] TodoItem key=2
54
+ │ └─ @c8 [fn] TodoItem key=3
55
+ └─ @c9 [fn] Footer
56
56
  ```
57
57
 
58
58
  Inspect a component's props, state, and hooks:
@@ -62,7 +62,7 @@ agent-react-devtools get component @c6
62
62
  ```
63
63
 
64
64
  ```
65
- @c6 [fn] "TodoItem" key="1"
65
+ @c6 [fn] TodoItem key=1
66
66
  props:
67
67
  id: 1
68
68
  text: "Buy groceries"
@@ -80,9 +80,9 @@ agent-react-devtools find TodoItem
80
80
  ```
81
81
 
82
82
  ```
83
- @c6 [fn] "TodoItem" key="1"
84
- @c7 [fn] "TodoItem" key="2"
85
- @c8 [fn] "TodoItem" key="3"
83
+ @c6 [fn] TodoItem key=1
84
+ @c7 [fn] TodoItem key=2
85
+ @c8 [fn] TodoItem key=3
86
86
  ```
87
87
 
88
88
  Profile rendering performance:
@@ -96,9 +96,9 @@ agent-react-devtools profile slow
96
96
 
97
97
  ```
98
98
  Slowest (by avg render time):
99
- TodoList avg:4.2ms max:8.1ms renders:6 cause:props
100
- SearchBar avg:2.1ms max:3.4ms renders:12 cause:hooks
101
- Header avg:0.8ms max:1.2ms renders:3 cause:parent
99
+ @c5 [fn] TodoList avg:4.2ms max:8.1ms renders:6 causes:props-changed
100
+ @c4 [fn] SearchBar avg:2.1ms max:3.4ms renders:12 causes:hooks-changed
101
+ @c2 [fn] Header avg:0.8ms max:1.2ms renders:3 causes:parent-rendered
102
102
  ```
103
103
 
104
104
  ## Commands
package/dist/cli.js CHANGED
@@ -130,6 +130,13 @@ var TYPE_ABBREV = {
130
130
  function typeTag(type) {
131
131
  return TYPE_ABBREV[type] || type;
132
132
  }
133
+ function formatRef(opts) {
134
+ const ref = opts.label || "?";
135
+ const tag = typeTag(opts.type || "other");
136
+ let s = `${ref} [${tag}] ${opts.name}`;
137
+ if (opts.key) s += ` key=${opts.key}`;
138
+ return s;
139
+ }
133
140
  var PIPE = "\u2502 ";
134
141
  var TEE = "\u251C\u2500 ";
135
142
  var ELBOW = "\u2514\u2500 ";
@@ -151,8 +158,7 @@ function formatTree(nodes) {
151
158
  const node = nodes.find((n) => n.id === nodeId);
152
159
  if (!node) return;
153
160
  const connector = isRoot ? "" : isLast ? ELBOW : TEE;
154
- let line = `${node.label} [${typeTag(node.type)}] "${node.displayName}"`;
155
- if (node.key) line += ` key="${node.key}"`;
161
+ const line = formatRef({ label: node.label, type: node.type, name: node.displayName, key: node.key });
156
162
  lines.push(`${prefix}${connector}${line}`);
157
163
  const children = childrenMap.get(node.id) || [];
158
164
  const childPrefix = isRoot ? "" : prefix + (isLast ? SPACE : PIPE);
@@ -168,10 +174,7 @@ function formatTree(nodes) {
168
174
  }
169
175
  function formatComponent(element, label) {
170
176
  const lines = [];
171
- const ref = label || `#${element.id}`;
172
- let header = `${ref} [${typeTag(element.type)}] "${element.displayName}"`;
173
- if (element.key) header += ` key="${element.key}"`;
174
- lines.push(header);
177
+ lines.push(formatRef({ label: label || `#${element.id}`, type: element.type, name: element.displayName, key: element.key }));
175
178
  if (element.props && Object.keys(element.props).length > 0) {
176
179
  lines.push("props:");
177
180
  for (const [key, value] of Object.entries(element.props)) {
@@ -201,11 +204,7 @@ function formatComponent(element, label) {
201
204
  }
202
205
  function formatSearchResults(results) {
203
206
  if (results.length === 0) return "No components found";
204
- return results.map((n) => {
205
- let line = `${n.label} [${typeTag(n.type)}] "${n.displayName}"`;
206
- if (n.key) line += ` key="${n.key}"`;
207
- return line;
208
- }).join("\n");
207
+ return results.map((n) => formatRef({ label: n.label, type: n.type, name: n.displayName, key: n.key })).join("\n");
209
208
  }
210
209
  function formatCount(counts) {
211
210
  const total = Object.values(counts).reduce((a, b) => a + b, 0);
@@ -235,16 +234,15 @@ function formatProfileSummary(summary) {
235
234
  lines.push("");
236
235
  lines.push("Top renders:");
237
236
  for (const c of summary.componentRenderCounts.slice(0, 10)) {
238
- const name = c.displayName || `#${c.id}`;
239
- lines.push(` ${name} ${c.count} renders`);
237
+ const ref = formatRef({ label: c.label, type: c.type, name: c.displayName || `#${c.id}` });
238
+ lines.push(` ${ref} ${c.count} renders`);
240
239
  }
241
240
  }
242
241
  return lines.join("\n");
243
242
  }
244
243
  function formatProfileReport(report, label) {
245
244
  const lines = [];
246
- const ref = label || `#${report.id}`;
247
- lines.push(`${ref} "${report.displayName}"`);
245
+ lines.push(formatRef({ label: label || report.label || `#${report.id}`, type: report.type, name: report.displayName }));
248
246
  lines.push(
249
247
  `renders:${report.renderCount} avg:${report.avgDuration.toFixed(1)}ms max:${report.maxDuration.toFixed(1)}ms total:${report.totalDuration.toFixed(1)}ms`
250
248
  );
@@ -257,9 +255,10 @@ function formatSlowest(reports) {
257
255
  if (reports.length === 0) return "No profiling data";
258
256
  const lines = ["Slowest (by avg render time):"];
259
257
  for (const r of reports) {
260
- const cause = r.causes[0] || "?";
258
+ const ref = formatRef({ label: r.label, type: r.type, name: r.displayName });
259
+ const causes = r.causes.length > 0 ? r.causes.join(", ") : "?";
261
260
  lines.push(
262
- ` ${pad(r.displayName, 20)} avg:${r.avgDuration.toFixed(1)}ms max:${r.maxDuration.toFixed(1)}ms renders:${r.renderCount} cause:${cause}`
261
+ ` ${ref} avg:${r.avgDuration.toFixed(1)}ms max:${r.maxDuration.toFixed(1)}ms renders:${r.renderCount} causes:${causes}`
263
262
  );
264
263
  }
265
264
  return lines.join("\n");
@@ -268,9 +267,10 @@ function formatRerenders(reports) {
268
267
  if (reports.length === 0) return "No profiling data";
269
268
  const lines = ["Most re-renders:"];
270
269
  for (const r of reports) {
271
- const cause = r.causes[0] || "?";
270
+ const ref = formatRef({ label: r.label, type: r.type, name: r.displayName });
271
+ const causes = r.causes.length > 0 ? r.causes.join(", ") : "?";
272
272
  lines.push(
273
- ` ${pad(r.displayName, 20)} ${r.renderCount} renders \u2014 ${cause}`
273
+ ` ${ref} ${r.renderCount} renders causes:${causes}`
274
274
  );
275
275
  }
276
276
  return lines.join("\n");
@@ -290,8 +290,9 @@ function formatCommitDetail(detail) {
290
290
  lines.push(`Commit #${detail.index} ${detail.duration.toFixed(1)}ms ${detail.totalComponents} components`);
291
291
  lines.push("");
292
292
  for (const c of detail.components) {
293
+ const ref = formatRef({ label: c.label, type: c.type, name: c.displayName });
293
294
  const causes = c.causes.length > 0 ? c.causes.join(", ") : "?";
294
- lines.push(` ${pad(c.displayName, 24)} self:${c.selfDuration.toFixed(1)}ms total:${c.actualDuration.toFixed(1)}ms ${causes}`);
295
+ lines.push(` ${ref} self:${c.selfDuration.toFixed(1)}ms total:${c.actualDuration.toFixed(1)}ms causes:${causes}`);
295
296
  }
296
297
  const hidden = detail.totalComponents - detail.components.length;
297
298
  if (hidden > 0) {
@@ -317,9 +318,6 @@ function replacer(_key, value) {
317
318
  if (typeof value === "function") return "\u0192";
318
319
  return value;
319
320
  }
320
- function pad(s, len) {
321
- return s.length >= len ? s : s + " ".repeat(len - s.length);
322
- }
323
321
 
324
322
  // src/cli.ts
325
323
  function usage() {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/daemon-client.ts","../src/formatters.ts","../src/cli.ts"],"sourcesContent":["import net from 'node:net';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport type { IpcCommand, IpcResponse, DaemonInfo } from './types.js';\n\nconst DEFAULT_STATE_DIR = path.join(\n process.env.HOME || process.env.USERPROFILE || '/tmp',\n '.agent-react-devtools',\n);\n\nlet stateDir = DEFAULT_STATE_DIR;\n\nexport function setStateDir(dir: string): void {\n stateDir = dir;\n}\n\nfunction getDaemonInfoPath(): string {\n return path.join(stateDir, 'daemon.json');\n}\n\nfunction getSocketPath(): string {\n return path.join(stateDir, 'daemon.sock');\n}\n\nexport function readDaemonInfo(): DaemonInfo | null {\n try {\n const raw = fs.readFileSync(getDaemonInfoPath(), 'utf-8');\n return JSON.parse(raw) as DaemonInfo;\n } catch {\n return null;\n }\n}\n\nfunction isDaemonAlive(info: DaemonInfo): boolean {\n try {\n // Signal 0 doesn't kill, just checks if process exists\n process.kill(info.pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function ensureDaemon(port?: number): Promise<void> {\n const info = readDaemonInfo();\n if (info && isDaemonAlive(info)) {\n return; // Already running\n }\n\n // Clean up stale files\n try {\n fs.unlinkSync(getDaemonInfoPath());\n } catch {\n // ignore\n }\n try {\n fs.unlinkSync(getSocketPath());\n } catch {\n // ignore\n }\n\n // Start daemon as detached child process\n const daemonScript = path.join(\n path.dirname(new URL(import.meta.url).pathname),\n 'daemon.js',\n );\n\n const args = [];\n if (port) args.push(`--port=${port}`);\n if (stateDir !== DEFAULT_STATE_DIR) args.push(`--state-dir=${stateDir}`);\n\n const child = spawn(process.execPath, [daemonScript, ...args], {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n\n // Wait for daemon to be ready (up to 5 seconds)\n const deadline = Date.now() + 5000;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, 100));\n try {\n await sendCommand({ type: 'ping' });\n return;\n } catch {\n // not ready yet\n }\n }\n throw new Error('Daemon failed to start within 5 seconds');\n}\n\nexport function stopDaemon(): boolean {\n const info = readDaemonInfo();\n if (!info) return false;\n\n try {\n process.kill(info.pid, 'SIGTERM');\n // Clean up files\n try {\n fs.unlinkSync(getDaemonInfoPath());\n } catch {\n // ignore\n }\n return true;\n } catch {\n return false;\n }\n}\n\nexport function sendCommand(cmd: IpcCommand): Promise<IpcResponse> {\n return new Promise((resolve, reject) => {\n const socketPath = getSocketPath();\n\n const conn = net.createConnection(socketPath, () => {\n conn.write(JSON.stringify(cmd) + '\\n');\n });\n\n let buffer = '';\n conn.on('data', (chunk) => {\n buffer += chunk.toString();\n const newlineIdx = buffer.indexOf('\\n');\n if (newlineIdx !== -1) {\n const line = buffer.slice(0, newlineIdx);\n conn.end();\n try {\n resolve(JSON.parse(line) as IpcResponse);\n } catch {\n reject(new Error('Invalid response from daemon'));\n }\n }\n });\n\n conn.on('error', (err) => {\n reject(new Error(`Cannot connect to daemon: ${err.message}`));\n });\n\n // Timeout after 30 seconds\n conn.setTimeout(30_000, () => {\n conn.destroy();\n reject(new Error('Command timed out'));\n });\n });\n}\n","import type {\n StatusInfo,\n InspectedElement,\n ComponentRenderReport,\n} from './types.js';\nimport type { TreeNode } from './component-tree.js';\nimport type { ProfileSummary, TimelineEntry, CommitDetail } from './profiler.js';\n\n// ── Abbreviations for component types ──\nconst TYPE_ABBREV: Record<string, string> = {\n function: 'fn',\n class: 'cls',\n host: 'host',\n memo: 'memo',\n forwardRef: 'fRef',\n profiler: 'prof',\n suspense: 'susp',\n context: 'ctx',\n other: '?',\n};\n\nfunction typeTag(type: string): string {\n return TYPE_ABBREV[type] || type;\n}\n\n// ── Tree connector characters ──\nconst PIPE = '│ ';\nconst TEE = '├─ ';\nconst ELBOW = '└─ ';\nconst SPACE = ' ';\n\nexport function formatTree(nodes: TreeNode[]): string {\n if (nodes.length === 0) return 'No components (is a React app connected?)';\n\n // Build tree structure from the flat list\n const childrenMap = new Map<number | null, TreeNode[]>();\n for (const node of nodes) {\n const parentId = node.parentId;\n let siblings = childrenMap.get(parentId);\n if (!siblings) {\n siblings = [];\n childrenMap.set(parentId, siblings);\n }\n siblings.push(node);\n }\n\n const lines: string[] = [];\n\n function walk(nodeId: number, prefix: string, isLast: boolean, isRoot: boolean): void {\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) return;\n\n const connector = isRoot ? '' : isLast ? ELBOW : TEE;\n let line = `${node.label} [${typeTag(node.type)}] \"${node.displayName}\"`;\n if (node.key) line += ` key=\"${node.key}\"`;\n\n lines.push(`${prefix}${connector}${line}`);\n\n const children = childrenMap.get(node.id) || [];\n const childPrefix = isRoot ? '' : prefix + (isLast ? SPACE : PIPE);\n\n for (let i = 0; i < children.length; i++) {\n walk(children[i].id, childPrefix, i === children.length - 1, false);\n }\n }\n\n // Find root nodes\n const roots = childrenMap.get(null) || [];\n for (let i = 0; i < roots.length; i++) {\n walk(roots[i].id, '', i === roots.length - 1, true);\n }\n\n return lines.join('\\n');\n}\n\nexport function formatComponent(element: InspectedElement, label?: string): string {\n const lines: string[] = [];\n\n const ref = label || `#${element.id}`;\n let header = `${ref} [${typeTag(element.type)}] \"${element.displayName}\"`;\n if (element.key) header += ` key=\"${element.key}\"`;\n lines.push(header);\n\n // Props\n if (element.props && Object.keys(element.props).length > 0) {\n lines.push('props:');\n for (const [key, value] of Object.entries(element.props)) {\n lines.push(` ${key}: ${formatCompactValue(value) ?? 'undefined'}`);\n }\n }\n\n // State\n if (element.state && Object.keys(element.state).length > 0) {\n lines.push('state:');\n for (const [key, value] of Object.entries(element.state)) {\n lines.push(` ${key}: ${formatCompactValue(value) ?? 'undefined'}`);\n }\n }\n\n // Hooks\n if (element.hooks && element.hooks.length > 0) {\n lines.push('hooks:');\n for (const h of element.hooks) {\n const val = formatCompactValue(h.value);\n lines.push(val !== undefined ? ` ${h.name}: ${val}` : ` ${h.name}`);\n if (h.subHooks && h.subHooks.length > 0) {\n for (const sh of h.subHooks) {\n const sval = formatCompactValue(sh.value);\n lines.push(sval !== undefined ? ` ${sh.name}: ${sval}` : ` ${sh.name}`);\n }\n }\n }\n }\n\n return lines.join('\\n');\n}\n\nexport function formatSearchResults(results: TreeNode[]): string {\n if (results.length === 0) return 'No components found';\n\n return results\n .map((n) => {\n let line = `${n.label} [${typeTag(n.type)}] \"${n.displayName}\"`;\n if (n.key) line += ` key=\"${n.key}\"`;\n return line;\n })\n .join('\\n');\n}\n\nexport function formatCount(counts: Record<string, number>): string {\n const total = Object.values(counts).reduce((a, b) => a + b, 0);\n const parts = Object.entries(counts)\n .sort((a, b) => b[1] - a[1])\n .map(([type, count]) => `${typeTag(type)}:${count}`)\n .join(' ');\n return `${total} components (${parts})`;\n}\n\nexport function formatStatus(status: StatusInfo): string {\n const lines: string[] = [];\n lines.push(`Daemon: running (port ${status.port})`);\n lines.push(\n `Apps: ${status.connectedApps} connected, ${status.componentCount} components`,\n );\n if (status.profilingActive) {\n lines.push('Profiling: active');\n }\n const upSec = Math.round(status.uptime / 1000);\n lines.push(`Uptime: ${upSec}s`);\n return lines.join('\\n');\n}\n\nexport function formatProfileSummary(summary: ProfileSummary): string {\n const lines: string[] = [];\n const durSec = (summary.duration / 1000).toFixed(1);\n lines.push(\n `Profile \"${summary.name}\" (${durSec}s, ${summary.commitCount} commits)`,\n );\n\n if (summary.componentRenderCounts.length > 0) {\n lines.push('');\n lines.push('Top renders:');\n for (const c of summary.componentRenderCounts.slice(0, 10)) {\n const name = c.displayName || `#${c.id}`;\n lines.push(` ${name} ${c.count} renders`);\n }\n }\n\n return lines.join('\\n');\n}\n\nexport function formatProfileReport(report: ComponentRenderReport, label?: string): string {\n const lines: string[] = [];\n const ref = label || `#${report.id}`;\n lines.push(`${ref} \"${report.displayName}\"`);\n lines.push(\n `renders:${report.renderCount} avg:${report.avgDuration.toFixed(1)}ms max:${report.maxDuration.toFixed(1)}ms total:${report.totalDuration.toFixed(1)}ms`,\n );\n if (report.causes.length > 0) {\n lines.push(`causes: ${report.causes.join(', ')}`);\n }\n return lines.join('\\n');\n}\n\nexport function formatSlowest(reports: ComponentRenderReport[]): string {\n if (reports.length === 0) return 'No profiling data';\n\n const lines: string[] = ['Slowest (by avg render time):'];\n for (const r of reports) {\n const cause = r.causes[0] || '?';\n lines.push(\n ` ${pad(r.displayName, 20)} avg:${r.avgDuration.toFixed(1)}ms max:${r.maxDuration.toFixed(1)}ms renders:${r.renderCount} cause:${cause}`,\n );\n }\n return lines.join('\\n');\n}\n\nexport function formatRerenders(reports: ComponentRenderReport[]): string {\n if (reports.length === 0) return 'No profiling data';\n\n const lines: string[] = ['Most re-renders:'];\n for (const r of reports) {\n const cause = r.causes[0] || '?';\n lines.push(\n ` ${pad(r.displayName, 20)} ${r.renderCount} renders — ${cause}`,\n );\n }\n return lines.join('\\n');\n}\n\nexport function formatTimeline(entries: TimelineEntry[]): string {\n if (entries.length === 0) return 'No profiling data';\n\n const lines: string[] = ['Commit timeline:'];\n for (const e of entries) {\n lines.push(\n ` #${e.index} ${e.duration.toFixed(1)}ms ${e.componentCount} components`,\n );\n }\n return lines.join('\\n');\n}\n\nexport function formatCommitDetail(detail: CommitDetail): string {\n const lines: string[] = [];\n lines.push(`Commit #${detail.index} ${detail.duration.toFixed(1)}ms ${detail.totalComponents} components`);\n lines.push('');\n for (const c of detail.components) {\n const causes = c.causes.length > 0 ? c.causes.join(', ') : '?';\n lines.push(` ${pad(c.displayName, 24)} self:${c.selfDuration.toFixed(1)}ms total:${c.actualDuration.toFixed(1)}ms ${causes}`);\n }\n const hidden = detail.totalComponents - detail.components.length;\n if (hidden > 0) {\n lines.push(` ... ${hidden} more (use --limit to show more)`);\n }\n return lines.join('\\n');\n}\n\n// ── Helpers ──\n\nfunction formatValue(obj: unknown): string {\n try {\n return JSON.stringify(obj, replacer, 0) || 'undefined';\n } catch {\n return String(obj);\n }\n}\n\nfunction formatCompactValue(val: unknown): string | undefined {\n if (val === undefined) return undefined;\n if (val === null) return 'null';\n if (typeof val === 'function') return 'ƒ';\n if (typeof val === 'string') return `\"${val}\"`;\n if (typeof val === 'number' || typeof val === 'boolean') return String(val);\n try {\n const s = JSON.stringify(val, replacer, 0);\n if (s && s.length > 60) return s.slice(0, 57) + '...';\n return s || String(val);\n } catch {\n return String(val);\n }\n}\n\nfunction replacer(_key: string, value: unknown): unknown {\n if (typeof value === 'function') return 'ƒ';\n return value;\n}\n\nfunction pad(s: string, len: number): string {\n return s.length >= len ? s : s + ' '.repeat(len - s.length);\n}\n","import {\n ensureDaemon,\n sendCommand,\n stopDaemon,\n readDaemonInfo,\n setStateDir,\n} from './daemon-client.js';\nimport {\n formatTree,\n formatComponent,\n formatSearchResults,\n formatCount,\n formatStatus,\n formatProfileSummary,\n formatProfileReport,\n formatSlowest,\n formatRerenders,\n formatTimeline,\n formatCommitDetail,\n} from './formatters.js';\nimport type { IpcCommand } from './types.js';\n\nfunction usage(): string {\n return `Usage: devtools <command> [options]\n\nSetup:\n init [--dry-run] Auto-configure your React app\n\nDaemon:\n start [--port 8097] Start daemon\n stop Stop daemon\n status Show daemon status\n\nComponents:\n get tree [--depth N] Component hierarchy\n get component <@c1 | id> Props, state, hooks\n find <name> [--exact] Search by display name\n count Component count by type\n\nProfiling:\n profile start [name] Start profiling session\n profile stop Stop profiling, collect data\n profile report <@c1 | id> Render report for component\n profile slow [--limit N] Slowest components (by avg)\n profile rerenders [--limit N] Most re-rendered components\n profile timeline [--limit N] Commit timeline\n profile commit <N | #N> [--limit N] Detail for specific commit`;\n}\n\nfunction parseArgs(argv: string[]): {\n command: string[];\n flags: Record<string, string | boolean>;\n} {\n const command: string[] = [];\n const flags: Record<string, string | boolean> = {};\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg.startsWith('--')) {\n const key = arg.slice(2);\n const eqIdx = key.indexOf('=');\n if (eqIdx !== -1) {\n flags[key.slice(0, eqIdx)] = key.slice(eqIdx + 1);\n } else {\n // Check if next arg is a value\n const next = argv[i + 1];\n if (next && !next.startsWith('--')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = true;\n }\n }\n } else {\n command.push(arg);\n }\n }\n return { command, flags };\n}\n\nasync function main(): Promise<void> {\n const { command, flags } = parseArgs(process.argv.slice(2));\n\n if (command.length === 0 || flags['help']) {\n console.log(usage());\n process.exit(0);\n }\n\n // Configure custom state directory (for test isolation)\n if (typeof flags['state-dir'] === 'string') {\n setStateDir(flags['state-dir']);\n }\n\n const cmd0 = command[0];\n const cmd1 = command[1];\n\n try {\n // ── Init ──\n if (cmd0 === 'init') {\n const { runInit } = await import('./init.js');\n await runInit(process.cwd(), flags['dry-run'] === true);\n return;\n }\n\n // ── Daemon management ──\n if (cmd0 === 'start') {\n const port = flags['port'] ? parseInt(flags['port'] as string, 10) : undefined;\n await ensureDaemon(port);\n const resp = await sendCommand({ type: 'status' });\n if (resp.ok) {\n console.log(formatStatus(resp.data as any));\n }\n return;\n }\n\n if (cmd0 === 'stop') {\n const stopped = stopDaemon();\n console.log(stopped ? 'Daemon stopped' : 'Daemon is not running');\n return;\n }\n\n if (cmd0 === 'status') {\n const info = readDaemonInfo();\n if (!info) {\n console.log('Daemon is not running');\n process.exit(1);\n }\n try {\n const resp = await sendCommand({ type: 'status' });\n if (resp.ok) {\n console.log(formatStatus(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n } catch {\n console.log('Daemon is not running (stale info)');\n process.exit(1);\n }\n return;\n }\n\n // ── All other commands require the daemon ──\n await ensureDaemon();\n\n // ── Component inspection ──\n if (cmd0 === 'get' && cmd1 === 'tree') {\n const depth = flags['depth']\n ? parseInt(flags['depth'] as string, 10)\n : undefined;\n const ipcCmd: IpcCommand = { type: 'get-tree', depth };\n const resp = await sendCommand(ipcCmd);\n if (resp.ok) {\n console.log(formatTree(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'get' && cmd1 === 'component') {\n const raw = command[2];\n if (!raw) {\n console.error('Usage: devtools get component <@c1 | id>');\n process.exit(1);\n }\n const id: number | string = raw.startsWith('@') ? raw : parseInt(raw, 10);\n if (typeof id === 'number' && isNaN(id)) {\n console.error('Usage: devtools get component <@c1 | id>');\n process.exit(1);\n }\n const resp = await sendCommand({ type: 'get-component', id });\n if (resp.ok) {\n console.log(formatComponent(resp.data as any, resp.label));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'find') {\n const name = command[1];\n if (!name) {\n console.error('Usage: devtools find <name> [--exact]');\n process.exit(1);\n }\n const exact = flags['exact'] === true;\n const resp = await sendCommand({ type: 'find', name, exact });\n if (resp.ok) {\n console.log(formatSearchResults(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'count') {\n const resp = await sendCommand({ type: 'count' });\n if (resp.ok) {\n console.log(formatCount(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n // ── Profiling ──\n if (cmd0 === 'profile' && cmd1 === 'start') {\n const name = command[2];\n const resp = await sendCommand({ type: 'profile-start', name });\n if (resp.ok) {\n console.log(resp.data);\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'stop') {\n const resp = await sendCommand({ type: 'profile-stop' });\n if (resp.ok) {\n console.log(formatProfileSummary(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'report') {\n const raw = command[2];\n if (!raw) {\n console.error('Usage: devtools profile report <@c1 | id>');\n process.exit(1);\n }\n const componentId: number | string = raw.startsWith('@') ? raw : parseInt(raw, 10);\n if (typeof componentId === 'number' && isNaN(componentId)) {\n console.error('Usage: devtools profile report <@c1 | id>');\n process.exit(1);\n }\n const resp = await sendCommand({ type: 'profile-report', componentId });\n if (resp.ok) {\n console.log(formatProfileReport(resp.data as any, resp.label));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'slow') {\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-slow', limit });\n if (resp.ok) {\n console.log(formatSlowest(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'rerenders') {\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-rerenders', limit });\n if (resp.ok) {\n console.log(formatRerenders(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'commit') {\n const raw = command[2];\n if (!raw) {\n console.error('Usage: devtools profile commit <N | #N>');\n process.exit(1);\n }\n const index = parseInt(raw.replace(/^#/, ''), 10);\n if (isNaN(index)) {\n console.error('Usage: devtools profile commit <N | #N>');\n process.exit(1);\n }\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-commit', index, limit });\n if (resp.ok) {\n console.log(formatCommitDetail(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'timeline') {\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-timeline', limit });\n if (resp.ok) {\n console.log(formatTimeline(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n console.error(`Unknown command: ${command.join(' ')}`);\n console.log(usage());\n process.exit(1);\n } catch (err) {\n console.error(\n err instanceof Error ? err.message : String(err),\n );\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/daemon-client.ts","../src/formatters.ts","../src/cli.ts"],"sourcesContent":["import net from 'node:net';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport type { IpcCommand, IpcResponse, DaemonInfo } from './types.js';\n\nconst DEFAULT_STATE_DIR = path.join(\n process.env.HOME || process.env.USERPROFILE || '/tmp',\n '.agent-react-devtools',\n);\n\nlet stateDir = DEFAULT_STATE_DIR;\n\nexport function setStateDir(dir: string): void {\n stateDir = dir;\n}\n\nfunction getDaemonInfoPath(): string {\n return path.join(stateDir, 'daemon.json');\n}\n\nfunction getSocketPath(): string {\n return path.join(stateDir, 'daemon.sock');\n}\n\nexport function readDaemonInfo(): DaemonInfo | null {\n try {\n const raw = fs.readFileSync(getDaemonInfoPath(), 'utf-8');\n return JSON.parse(raw) as DaemonInfo;\n } catch {\n return null;\n }\n}\n\nfunction isDaemonAlive(info: DaemonInfo): boolean {\n try {\n // Signal 0 doesn't kill, just checks if process exists\n process.kill(info.pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function ensureDaemon(port?: number): Promise<void> {\n const info = readDaemonInfo();\n if (info && isDaemonAlive(info)) {\n return; // Already running\n }\n\n // Clean up stale files\n try {\n fs.unlinkSync(getDaemonInfoPath());\n } catch {\n // ignore\n }\n try {\n fs.unlinkSync(getSocketPath());\n } catch {\n // ignore\n }\n\n // Start daemon as detached child process\n const daemonScript = path.join(\n path.dirname(new URL(import.meta.url).pathname),\n 'daemon.js',\n );\n\n const args = [];\n if (port) args.push(`--port=${port}`);\n if (stateDir !== DEFAULT_STATE_DIR) args.push(`--state-dir=${stateDir}`);\n\n const child = spawn(process.execPath, [daemonScript, ...args], {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n\n // Wait for daemon to be ready (up to 5 seconds)\n const deadline = Date.now() + 5000;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, 100));\n try {\n await sendCommand({ type: 'ping' });\n return;\n } catch {\n // not ready yet\n }\n }\n throw new Error('Daemon failed to start within 5 seconds');\n}\n\nexport function stopDaemon(): boolean {\n const info = readDaemonInfo();\n if (!info) return false;\n\n try {\n process.kill(info.pid, 'SIGTERM');\n // Clean up files\n try {\n fs.unlinkSync(getDaemonInfoPath());\n } catch {\n // ignore\n }\n return true;\n } catch {\n return false;\n }\n}\n\nexport function sendCommand(cmd: IpcCommand): Promise<IpcResponse> {\n return new Promise((resolve, reject) => {\n const socketPath = getSocketPath();\n\n const conn = net.createConnection(socketPath, () => {\n conn.write(JSON.stringify(cmd) + '\\n');\n });\n\n let buffer = '';\n conn.on('data', (chunk) => {\n buffer += chunk.toString();\n const newlineIdx = buffer.indexOf('\\n');\n if (newlineIdx !== -1) {\n const line = buffer.slice(0, newlineIdx);\n conn.end();\n try {\n resolve(JSON.parse(line) as IpcResponse);\n } catch {\n reject(new Error('Invalid response from daemon'));\n }\n }\n });\n\n conn.on('error', (err) => {\n reject(new Error(`Cannot connect to daemon: ${err.message}`));\n });\n\n // Timeout after 30 seconds\n conn.setTimeout(30_000, () => {\n conn.destroy();\n reject(new Error('Command timed out'));\n });\n });\n}\n","import type {\n StatusInfo,\n InspectedElement,\n ComponentRenderReport,\n} from './types.js';\nimport type { TreeNode } from './component-tree.js';\nimport type { ProfileSummary, TimelineEntry, CommitDetail } from './profiler.js';\n\n// ── Abbreviations for component types ──\nconst TYPE_ABBREV: Record<string, string> = {\n function: 'fn',\n class: 'cls',\n host: 'host',\n memo: 'memo',\n forwardRef: 'fRef',\n profiler: 'prof',\n suspense: 'susp',\n context: 'ctx',\n other: '?',\n};\n\nfunction typeTag(type: string): string {\n return TYPE_ABBREV[type] || type;\n}\n\n/**\n * Format a consistent component reference: `@c1 [fn] Name` or `@c1 [fn] Name key=x`\n */\nfunction formatRef(opts: { label?: string; type?: string; name: string; key?: string | null }): string {\n const ref = opts.label || '?';\n const tag = typeTag(opts.type || 'other');\n let s = `${ref} [${tag}] ${opts.name}`;\n if (opts.key) s += ` key=${opts.key}`;\n return s;\n}\n\n// ── Tree connector characters ──\nconst PIPE = '│ ';\nconst TEE = '├─ ';\nconst ELBOW = '└─ ';\nconst SPACE = ' ';\n\nexport function formatTree(nodes: TreeNode[]): string {\n if (nodes.length === 0) return 'No components (is a React app connected?)';\n\n // Build tree structure from the flat list\n const childrenMap = new Map<number | null, TreeNode[]>();\n for (const node of nodes) {\n const parentId = node.parentId;\n let siblings = childrenMap.get(parentId);\n if (!siblings) {\n siblings = [];\n childrenMap.set(parentId, siblings);\n }\n siblings.push(node);\n }\n\n const lines: string[] = [];\n\n function walk(nodeId: number, prefix: string, isLast: boolean, isRoot: boolean): void {\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) return;\n\n const connector = isRoot ? '' : isLast ? ELBOW : TEE;\n const line = formatRef({ label: node.label, type: node.type, name: node.displayName, key: node.key });\n\n lines.push(`${prefix}${connector}${line}`);\n\n const children = childrenMap.get(node.id) || [];\n const childPrefix = isRoot ? '' : prefix + (isLast ? SPACE : PIPE);\n\n for (let i = 0; i < children.length; i++) {\n walk(children[i].id, childPrefix, i === children.length - 1, false);\n }\n }\n\n // Find root nodes\n const roots = childrenMap.get(null) || [];\n for (let i = 0; i < roots.length; i++) {\n walk(roots[i].id, '', i === roots.length - 1, true);\n }\n\n return lines.join('\\n');\n}\n\nexport function formatComponent(element: InspectedElement, label?: string): string {\n const lines: string[] = [];\n\n lines.push(formatRef({ label: label || `#${element.id}`, type: element.type, name: element.displayName, key: element.key }));\n\n // Props\n if (element.props && Object.keys(element.props).length > 0) {\n lines.push('props:');\n for (const [key, value] of Object.entries(element.props)) {\n lines.push(` ${key}: ${formatCompactValue(value) ?? 'undefined'}`);\n }\n }\n\n // State\n if (element.state && Object.keys(element.state).length > 0) {\n lines.push('state:');\n for (const [key, value] of Object.entries(element.state)) {\n lines.push(` ${key}: ${formatCompactValue(value) ?? 'undefined'}`);\n }\n }\n\n // Hooks\n if (element.hooks && element.hooks.length > 0) {\n lines.push('hooks:');\n for (const h of element.hooks) {\n const val = formatCompactValue(h.value);\n lines.push(val !== undefined ? ` ${h.name}: ${val}` : ` ${h.name}`);\n if (h.subHooks && h.subHooks.length > 0) {\n for (const sh of h.subHooks) {\n const sval = formatCompactValue(sh.value);\n lines.push(sval !== undefined ? ` ${sh.name}: ${sval}` : ` ${sh.name}`);\n }\n }\n }\n }\n\n return lines.join('\\n');\n}\n\nexport function formatSearchResults(results: TreeNode[]): string {\n if (results.length === 0) return 'No components found';\n\n return results\n .map((n) => formatRef({ label: n.label, type: n.type, name: n.displayName, key: n.key }))\n .join('\\n');\n}\n\nexport function formatCount(counts: Record<string, number>): string {\n const total = Object.values(counts).reduce((a, b) => a + b, 0);\n const parts = Object.entries(counts)\n .sort((a, b) => b[1] - a[1])\n .map(([type, count]) => `${typeTag(type)}:${count}`)\n .join(' ');\n return `${total} components (${parts})`;\n}\n\nexport function formatStatus(status: StatusInfo): string {\n const lines: string[] = [];\n lines.push(`Daemon: running (port ${status.port})`);\n lines.push(\n `Apps: ${status.connectedApps} connected, ${status.componentCount} components`,\n );\n if (status.profilingActive) {\n lines.push('Profiling: active');\n }\n const upSec = Math.round(status.uptime / 1000);\n lines.push(`Uptime: ${upSec}s`);\n return lines.join('\\n');\n}\n\nexport function formatProfileSummary(summary: ProfileSummary): string {\n const lines: string[] = [];\n const durSec = (summary.duration / 1000).toFixed(1);\n lines.push(\n `Profile \"${summary.name}\" (${durSec}s, ${summary.commitCount} commits)`,\n );\n\n if (summary.componentRenderCounts.length > 0) {\n lines.push('');\n lines.push('Top renders:');\n for (const c of summary.componentRenderCounts.slice(0, 10)) {\n const ref = formatRef({ label: c.label, type: c.type, name: c.displayName || `#${c.id}` });\n lines.push(` ${ref} ${c.count} renders`);\n }\n }\n\n return lines.join('\\n');\n}\n\nexport function formatProfileReport(report: ComponentRenderReport, label?: string): string {\n const lines: string[] = [];\n lines.push(formatRef({ label: label || report.label || `#${report.id}`, type: report.type, name: report.displayName }));\n lines.push(\n `renders:${report.renderCount} avg:${report.avgDuration.toFixed(1)}ms max:${report.maxDuration.toFixed(1)}ms total:${report.totalDuration.toFixed(1)}ms`,\n );\n if (report.causes.length > 0) {\n lines.push(`causes: ${report.causes.join(', ')}`);\n }\n return lines.join('\\n');\n}\n\nexport function formatSlowest(reports: ComponentRenderReport[]): string {\n if (reports.length === 0) return 'No profiling data';\n\n const lines: string[] = ['Slowest (by avg render time):'];\n for (const r of reports) {\n const ref = formatRef({ label: r.label, type: r.type, name: r.displayName });\n const causes = r.causes.length > 0 ? r.causes.join(', ') : '?';\n lines.push(\n ` ${ref} avg:${r.avgDuration.toFixed(1)}ms max:${r.maxDuration.toFixed(1)}ms renders:${r.renderCount} causes:${causes}`,\n );\n }\n return lines.join('\\n');\n}\n\nexport function formatRerenders(reports: ComponentRenderReport[]): string {\n if (reports.length === 0) return 'No profiling data';\n\n const lines: string[] = ['Most re-renders:'];\n for (const r of reports) {\n const ref = formatRef({ label: r.label, type: r.type, name: r.displayName });\n const causes = r.causes.length > 0 ? r.causes.join(', ') : '?';\n lines.push(\n ` ${ref} ${r.renderCount} renders causes:${causes}`,\n );\n }\n return lines.join('\\n');\n}\n\nexport function formatTimeline(entries: TimelineEntry[]): string {\n if (entries.length === 0) return 'No profiling data';\n\n const lines: string[] = ['Commit timeline:'];\n for (const e of entries) {\n lines.push(\n ` #${e.index} ${e.duration.toFixed(1)}ms ${e.componentCount} components`,\n );\n }\n return lines.join('\\n');\n}\n\nexport function formatCommitDetail(detail: CommitDetail): string {\n const lines: string[] = [];\n lines.push(`Commit #${detail.index} ${detail.duration.toFixed(1)}ms ${detail.totalComponents} components`);\n lines.push('');\n for (const c of detail.components) {\n const ref = formatRef({ label: c.label, type: c.type, name: c.displayName });\n const causes = c.causes.length > 0 ? c.causes.join(', ') : '?';\n lines.push(` ${ref} self:${c.selfDuration.toFixed(1)}ms total:${c.actualDuration.toFixed(1)}ms causes:${causes}`);\n }\n const hidden = detail.totalComponents - detail.components.length;\n if (hidden > 0) {\n lines.push(` ... ${hidden} more (use --limit to show more)`);\n }\n return lines.join('\\n');\n}\n\n// ── Helpers ──\n\nfunction formatCompactValue(val: unknown): string | undefined {\n if (val === undefined) return undefined;\n if (val === null) return 'null';\n if (typeof val === 'function') return 'ƒ';\n if (typeof val === 'string') return `\"${val}\"`;\n if (typeof val === 'number' || typeof val === 'boolean') return String(val);\n try {\n const s = JSON.stringify(val, replacer, 0);\n if (s && s.length > 60) return s.slice(0, 57) + '...';\n return s || String(val);\n } catch {\n return String(val);\n }\n}\n\nfunction replacer(_key: string, value: unknown): unknown {\n if (typeof value === 'function') return 'ƒ';\n return value;\n}\n","import {\n ensureDaemon,\n sendCommand,\n stopDaemon,\n readDaemonInfo,\n setStateDir,\n} from './daemon-client.js';\nimport {\n formatTree,\n formatComponent,\n formatSearchResults,\n formatCount,\n formatStatus,\n formatProfileSummary,\n formatProfileReport,\n formatSlowest,\n formatRerenders,\n formatTimeline,\n formatCommitDetail,\n} from './formatters.js';\nimport type { IpcCommand } from './types.js';\n\nfunction usage(): string {\n return `Usage: devtools <command> [options]\n\nSetup:\n init [--dry-run] Auto-configure your React app\n\nDaemon:\n start [--port 8097] Start daemon\n stop Stop daemon\n status Show daemon status\n\nComponents:\n get tree [--depth N] Component hierarchy\n get component <@c1 | id> Props, state, hooks\n find <name> [--exact] Search by display name\n count Component count by type\n\nProfiling:\n profile start [name] Start profiling session\n profile stop Stop profiling, collect data\n profile report <@c1 | id> Render report for component\n profile slow [--limit N] Slowest components (by avg)\n profile rerenders [--limit N] Most re-rendered components\n profile timeline [--limit N] Commit timeline\n profile commit <N | #N> [--limit N] Detail for specific commit`;\n}\n\nfunction parseArgs(argv: string[]): {\n command: string[];\n flags: Record<string, string | boolean>;\n} {\n const command: string[] = [];\n const flags: Record<string, string | boolean> = {};\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg.startsWith('--')) {\n const key = arg.slice(2);\n const eqIdx = key.indexOf('=');\n if (eqIdx !== -1) {\n flags[key.slice(0, eqIdx)] = key.slice(eqIdx + 1);\n } else {\n // Check if next arg is a value\n const next = argv[i + 1];\n if (next && !next.startsWith('--')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = true;\n }\n }\n } else {\n command.push(arg);\n }\n }\n return { command, flags };\n}\n\nasync function main(): Promise<void> {\n const { command, flags } = parseArgs(process.argv.slice(2));\n\n if (command.length === 0 || flags['help']) {\n console.log(usage());\n process.exit(0);\n }\n\n // Configure custom state directory (for test isolation)\n if (typeof flags['state-dir'] === 'string') {\n setStateDir(flags['state-dir']);\n }\n\n const cmd0 = command[0];\n const cmd1 = command[1];\n\n try {\n // ── Init ──\n if (cmd0 === 'init') {\n const { runInit } = await import('./init.js');\n await runInit(process.cwd(), flags['dry-run'] === true);\n return;\n }\n\n // ── Daemon management ──\n if (cmd0 === 'start') {\n const port = flags['port'] ? parseInt(flags['port'] as string, 10) : undefined;\n await ensureDaemon(port);\n const resp = await sendCommand({ type: 'status' });\n if (resp.ok) {\n console.log(formatStatus(resp.data as any));\n }\n return;\n }\n\n if (cmd0 === 'stop') {\n const stopped = stopDaemon();\n console.log(stopped ? 'Daemon stopped' : 'Daemon is not running');\n return;\n }\n\n if (cmd0 === 'status') {\n const info = readDaemonInfo();\n if (!info) {\n console.log('Daemon is not running');\n process.exit(1);\n }\n try {\n const resp = await sendCommand({ type: 'status' });\n if (resp.ok) {\n console.log(formatStatus(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n } catch {\n console.log('Daemon is not running (stale info)');\n process.exit(1);\n }\n return;\n }\n\n // ── All other commands require the daemon ──\n await ensureDaemon();\n\n // ── Component inspection ──\n if (cmd0 === 'get' && cmd1 === 'tree') {\n const depth = flags['depth']\n ? parseInt(flags['depth'] as string, 10)\n : undefined;\n const ipcCmd: IpcCommand = { type: 'get-tree', depth };\n const resp = await sendCommand(ipcCmd);\n if (resp.ok) {\n console.log(formatTree(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'get' && cmd1 === 'component') {\n const raw = command[2];\n if (!raw) {\n console.error('Usage: devtools get component <@c1 | id>');\n process.exit(1);\n }\n const id: number | string = raw.startsWith('@') ? raw : parseInt(raw, 10);\n if (typeof id === 'number' && isNaN(id)) {\n console.error('Usage: devtools get component <@c1 | id>');\n process.exit(1);\n }\n const resp = await sendCommand({ type: 'get-component', id });\n if (resp.ok) {\n console.log(formatComponent(resp.data as any, resp.label));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'find') {\n const name = command[1];\n if (!name) {\n console.error('Usage: devtools find <name> [--exact]');\n process.exit(1);\n }\n const exact = flags['exact'] === true;\n const resp = await sendCommand({ type: 'find', name, exact });\n if (resp.ok) {\n console.log(formatSearchResults(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'count') {\n const resp = await sendCommand({ type: 'count' });\n if (resp.ok) {\n console.log(formatCount(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n // ── Profiling ──\n if (cmd0 === 'profile' && cmd1 === 'start') {\n const name = command[2];\n const resp = await sendCommand({ type: 'profile-start', name });\n if (resp.ok) {\n console.log(resp.data);\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'stop') {\n const resp = await sendCommand({ type: 'profile-stop' });\n if (resp.ok) {\n console.log(formatProfileSummary(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'report') {\n const raw = command[2];\n if (!raw) {\n console.error('Usage: devtools profile report <@c1 | id>');\n process.exit(1);\n }\n const componentId: number | string = raw.startsWith('@') ? raw : parseInt(raw, 10);\n if (typeof componentId === 'number' && isNaN(componentId)) {\n console.error('Usage: devtools profile report <@c1 | id>');\n process.exit(1);\n }\n const resp = await sendCommand({ type: 'profile-report', componentId });\n if (resp.ok) {\n console.log(formatProfileReport(resp.data as any, resp.label));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'slow') {\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-slow', limit });\n if (resp.ok) {\n console.log(formatSlowest(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'rerenders') {\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-rerenders', limit });\n if (resp.ok) {\n console.log(formatRerenders(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'commit') {\n const raw = command[2];\n if (!raw) {\n console.error('Usage: devtools profile commit <N | #N>');\n process.exit(1);\n }\n const index = parseInt(raw.replace(/^#/, ''), 10);\n if (isNaN(index)) {\n console.error('Usage: devtools profile commit <N | #N>');\n process.exit(1);\n }\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-commit', index, limit });\n if (resp.ok) {\n console.log(formatCommitDetail(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'timeline') {\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-timeline', limit });\n if (resp.ok) {\n console.log(formatTimeline(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n console.error(`Unknown command: ${command.join(' ')}`);\n console.log(usage());\n process.exit(1);\n } catch (err) {\n console.error(\n err instanceof Error ? err.message : String(err),\n );\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":[]}
package/dist/daemon.js CHANGED
@@ -613,6 +613,13 @@ var ComponentTree = class {
613
613
  removeRoot(rootId) {
614
614
  this.removeNode(rootId);
615
615
  }
616
+ /**
617
+ * Look up the @cN label for a given component ID.
618
+ * Returns undefined if the ID has no label assigned.
619
+ */
620
+ getLabel(id) {
621
+ return this.idToLabel.get(id);
622
+ }
616
623
  /**
617
624
  * Resolve a label like "@c3" to a real node ID.
618
625
  * Returns undefined if label not found.
@@ -883,6 +890,15 @@ function getSocketPath() {
883
890
  function getDaemonInfoPath() {
884
891
  return path.join(STATE_DIR, "daemon.json");
885
892
  }
893
+ function enrichWithLabels(items, tree) {
894
+ for (const item of items) {
895
+ if (!item.label) item.label = tree.getLabel(item.id);
896
+ if (!item.type) {
897
+ const node = tree.getNode(item.id);
898
+ if (node) item.type = node.type;
899
+ }
900
+ }
901
+ }
886
902
  var Daemon = class {
887
903
  ipcServer = null;
888
904
  bridge;
@@ -1011,6 +1027,7 @@ var Daemon = class {
1011
1027
  if (!session) {
1012
1028
  return { ok: false, error: "No active profiling session" };
1013
1029
  }
1030
+ enrichWithLabels(session.componentRenderCounts, this.tree);
1014
1031
  return { ok: true, data: session };
1015
1032
  }
1016
1033
  case "profile-report": {
@@ -1025,19 +1042,20 @@ var Daemon = class {
1025
1042
  error: `No profiling data for component ${cmd.componentId}`
1026
1043
  };
1027
1044
  }
1045
+ enrichWithLabels([report], this.tree);
1028
1046
  const compLabel = typeof cmd.componentId === "string" ? cmd.componentId : void 0;
1029
1047
  return { ok: true, data: report, label: compLabel };
1030
1048
  }
1031
- case "profile-slow":
1032
- return {
1033
- ok: true,
1034
- data: this.profiler.getSlowest(this.tree, cmd.limit)
1035
- };
1036
- case "profile-rerenders":
1037
- return {
1038
- ok: true,
1039
- data: this.profiler.getMostRerenders(this.tree, cmd.limit)
1040
- };
1049
+ case "profile-slow": {
1050
+ const slowest = this.profiler.getSlowest(this.tree, cmd.limit);
1051
+ enrichWithLabels(slowest, this.tree);
1052
+ return { ok: true, data: slowest };
1053
+ }
1054
+ case "profile-rerenders": {
1055
+ const rerenders = this.profiler.getMostRerenders(this.tree, cmd.limit);
1056
+ enrichWithLabels(rerenders, this.tree);
1057
+ return { ok: true, data: rerenders };
1058
+ }
1041
1059
  case "profile-timeline":
1042
1060
  return {
1043
1061
  ok: true,
@@ -1048,6 +1066,7 @@ var Daemon = class {
1048
1066
  if (!detail) {
1049
1067
  return { ok: false, error: `Commit #${cmd.index} not found` };
1050
1068
  }
1069
+ enrichWithLabels(detail.components, this.tree);
1051
1070
  return { ok: true, data: detail };
1052
1071
  }
1053
1072
  default:
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/daemon.ts","../src/devtools-bridge.ts","../src/component-tree.ts","../src/profiler.ts"],"sourcesContent":["import net from 'node:net';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { DevToolsBridge } from './devtools-bridge.js';\nimport { ComponentTree } from './component-tree.js';\nimport { Profiler } from './profiler.js';\nimport type { IpcCommand, IpcResponse, DaemonInfo, StatusInfo } from './types.js';\n\nconst DEFAULT_STATE_DIR = path.join(\n process.env.HOME || process.env.USERPROFILE || '/tmp',\n '.agent-react-devtools',\n);\n\nlet STATE_DIR = DEFAULT_STATE_DIR;\n\nfunction getSocketPath(): string {\n return path.join(STATE_DIR, 'daemon.sock');\n}\n\nfunction getDaemonInfoPath(): string {\n return path.join(STATE_DIR, 'daemon.json');\n}\n\nclass Daemon {\n private ipcServer: net.Server | null = null;\n private bridge: DevToolsBridge;\n private tree: ComponentTree;\n private profiler: Profiler;\n private port: number;\n private startedAt = Date.now();\n\n constructor(port: number) {\n this.port = port;\n this.tree = new ComponentTree();\n this.profiler = new Profiler();\n this.bridge = new DevToolsBridge(port, this.tree, this.profiler);\n }\n\n async start(): Promise<void> {\n // Ensure state directory exists\n fs.mkdirSync(STATE_DIR, { recursive: true });\n\n // Clean up stale socket\n const socketPath = getSocketPath();\n if (fs.existsSync(socketPath)) {\n try {\n fs.unlinkSync(socketPath);\n } catch {\n // ignore\n }\n }\n\n // Start WebSocket bridge\n await this.bridge.start();\n\n // Start IPC server\n await this.startIpc(socketPath);\n\n // Write daemon info\n const info: DaemonInfo = {\n pid: process.pid,\n port: this.port,\n socketPath,\n startedAt: this.startedAt,\n };\n fs.writeFileSync(getDaemonInfoPath(), JSON.stringify(info, null, 2));\n\n console.log(`Daemon started (pid=${process.pid}, port=${this.port})`);\n\n // Handle shutdown\n const shutdown = () => {\n this.stop();\n process.exit(0);\n };\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n }\n\n private startIpc(socketPath: string): Promise<void> {\n return new Promise((resolve, reject) => {\n this.ipcServer = net.createServer((conn) => {\n let buffer = '';\n\n conn.on('data', (chunk) => {\n buffer += chunk.toString();\n\n // Process complete messages (newline-delimited JSON)\n let newlineIdx: number;\n while ((newlineIdx = buffer.indexOf('\\n')) !== -1) {\n const line = buffer.slice(0, newlineIdx);\n buffer = buffer.slice(newlineIdx + 1);\n\n try {\n const cmd: IpcCommand = JSON.parse(line);\n this.handleCommand(cmd).then((response) => {\n conn.write(JSON.stringify(response) + '\\n');\n });\n } catch {\n const response: IpcResponse = {\n ok: false,\n error: 'Invalid JSON',\n };\n conn.write(JSON.stringify(response) + '\\n');\n }\n }\n });\n });\n\n this.ipcServer.on('error', reject);\n\n this.ipcServer.listen(socketPath, () => {\n resolve();\n });\n });\n }\n\n private async handleCommand(cmd: IpcCommand): Promise<IpcResponse> {\n try {\n switch (cmd.type) {\n case 'ping':\n return { ok: true, data: 'pong' };\n\n case 'status':\n return {\n ok: true,\n data: {\n daemonRunning: true,\n port: this.port,\n connectedApps: this.bridge.getConnectedAppCount(),\n componentCount: this.tree.getComponentCount(),\n profilingActive: this.profiler.isActive(),\n uptime: Date.now() - this.startedAt,\n } satisfies StatusInfo,\n };\n\n case 'get-tree':\n return {\n ok: true,\n data: this.tree.getTree(cmd.depth),\n };\n\n case 'get-component': {\n const resolvedId = this.tree.resolveId(cmd.id);\n if (resolvedId === undefined) {\n return { ok: false, error: `Component ${cmd.id} not found` };\n }\n const element = await this.bridge.inspectElement(resolvedId);\n if (!element) {\n return { ok: false, error: `Component ${cmd.id} not found` };\n }\n // Include the label if the request used one\n const label = typeof cmd.id === 'string' ? cmd.id : undefined;\n return { ok: true, data: element, label };\n }\n\n case 'find':\n return {\n ok: true,\n data: this.tree.findByName(cmd.name, cmd.exact),\n };\n\n case 'count':\n return {\n ok: true,\n data: this.tree.getCountByType(),\n };\n\n case 'profile-start':\n this.profiler.start(cmd.name);\n // Snapshot existing component names so they survive unmounts\n for (const id of this.tree.getAllNodeIds()) {\n const node = this.tree.getNode(id);\n if (node) this.profiler.trackComponent(id, node.displayName);\n }\n this.bridge.startProfiling();\n return { ok: true, data: 'Profiling started' };\n\n case 'profile-stop': {\n await this.bridge.stopProfilingAndCollect();\n const session = this.profiler.stop(this.tree);\n if (!session) {\n return { ok: false, error: 'No active profiling session' };\n }\n return { ok: true, data: session };\n }\n\n case 'profile-report': {\n const resolvedCompId = this.tree.resolveId(cmd.componentId);\n if (resolvedCompId === undefined) {\n return { ok: false, error: `Component ${cmd.componentId} not found` };\n }\n const report = this.profiler.getReport(resolvedCompId, this.tree);\n if (!report) {\n return {\n ok: false,\n error: `No profiling data for component ${cmd.componentId}`,\n };\n }\n const compLabel = typeof cmd.componentId === 'string' ? cmd.componentId : undefined;\n return { ok: true, data: report, label: compLabel };\n }\n\n case 'profile-slow':\n return {\n ok: true,\n data: this.profiler.getSlowest(this.tree, cmd.limit),\n };\n\n case 'profile-rerenders':\n return {\n ok: true,\n data: this.profiler.getMostRerenders(this.tree, cmd.limit),\n };\n\n case 'profile-timeline':\n return {\n ok: true,\n data: this.profiler.getTimeline(cmd.limit),\n };\n\n case 'profile-commit': {\n const detail = this.profiler.getCommitDetails(cmd.index, this.tree, cmd.limit);\n if (!detail) {\n return { ok: false, error: `Commit #${cmd.index} not found` };\n }\n return { ok: true, data: detail };\n }\n\n default:\n return { ok: false, error: `Unknown command: ${(cmd as any).type}` };\n }\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n stop(): void {\n this.bridge.stop();\n if (this.ipcServer) {\n this.ipcServer.close();\n this.ipcServer = null;\n }\n // Clean up files\n try {\n fs.unlinkSync(getSocketPath());\n } catch {\n // ignore\n }\n try {\n fs.unlinkSync(getDaemonInfoPath());\n } catch {\n // ignore\n }\n console.log('Daemon stopped');\n }\n}\n\n// ── Main ──\n\nconst portArg = process.argv.find((a) => a.startsWith('--port='));\nconst port = portArg ? parseInt(portArg.split('=')[1], 10) : 8097;\n\nconst stateDirArg = process.argv.find((a) => a.startsWith('--state-dir='));\nif (stateDirArg) {\n STATE_DIR = stateDirArg.split('=')[1];\n}\n\nconst daemon = new Daemon(port);\ndaemon.start().catch((err) => {\n console.error('Failed to start daemon:', err);\n process.exit(1);\n});\n","import { WebSocketServer, WebSocket } from 'ws';\nimport type { ComponentTree } from './component-tree.js';\nimport type { Profiler } from './profiler.js';\nimport type { InspectedElement } from './types.js';\n\n/**\n * React DevTools protocol bridge.\n *\n * Implements the \"Wall\" messaging pattern that React DevTools uses:\n * - The backend (inside React app) sends operations, profiling data, etc.\n * - The frontend (us) can request element inspection, start/stop profiling, etc.\n *\n * Message format over WebSocket:\n * { event: string, payload: any }\n */\n\ninterface DevToolsMessage {\n event: string;\n payload: unknown;\n}\n\ninterface PendingInspection {\n resolve: (value: InspectedElement | null) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\ninterface PendingProfilingCollect {\n resolve: () => void;\n timer: ReturnType<typeof setTimeout>;\n remaining: number;\n}\n\nexport class DevToolsBridge {\n private wss: WebSocketServer | null = null;\n private connections = new Set<WebSocket>();\n private port: number;\n private tree: ComponentTree;\n private profiler: Profiler;\n private pendingInspections = new Map<number, PendingInspection>();\n private pendingProfilingCollect: PendingProfilingCollect | null = null;\n private rendererIds = new Set<number>();\n /** Track which root fiber IDs belong to each WebSocket connection */\n private connectionRoots = new Map<WebSocket, Set<number>>();\n\n constructor(port: number, tree: ComponentTree, profiler: Profiler) {\n this.port = port;\n this.tree = tree;\n this.profiler = profiler;\n }\n\n async start(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.wss = new WebSocketServer({ port: this.port }, () => {\n resolve();\n });\n\n this.wss.on('error', (err) => {\n reject(err);\n });\n\n this.wss.on('connection', (ws) => {\n this.connections.add(ws);\n\n ws.on('message', (data) => {\n try {\n const msg: DevToolsMessage = JSON.parse(data.toString());\n this.handleMessage(ws, msg);\n } catch {\n // ignore parse errors\n }\n });\n\n ws.on('close', () => {\n this.cleanupConnection(ws);\n });\n\n ws.on('error', () => {\n this.cleanupConnection(ws);\n });\n });\n });\n }\n\n stop(): void {\n for (const conn of this.connections) {\n conn.close();\n }\n this.connections.clear();\n if (this.wss) {\n this.wss.close();\n this.wss = null;\n }\n }\n\n getConnectedAppCount(): number {\n return this.connections.size;\n }\n\n /**\n * Request detailed inspection of a specific element.\n * Sends a request to the React app and waits for the response.\n */\n inspectElement(id: number): Promise<InspectedElement | null> {\n const node = this.tree.getNode(id);\n if (!node) return Promise.resolve(null);\n\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n this.pendingInspections.delete(id);\n resolve(null);\n }, 5000);\n\n this.pendingInspections.set(id, { resolve, timer });\n\n this.sendToAll({\n event: 'inspectElement',\n payload: {\n id,\n rendererID: node.rendererId,\n forceFullData: true,\n requestID: id,\n path: null,\n },\n });\n });\n }\n\n startProfiling(): void {\n this.sendToAll({\n event: 'startProfiling',\n payload: { recordChangeDescriptions: true },\n });\n }\n\n /**\n * Stop profiling and request data from each renderer.\n * Returns a promise that resolves when profilingData arrives (or 5s timeout).\n */\n stopProfilingAndCollect(): Promise<void> {\n this.sendToAll({\n event: 'stopProfiling',\n payload: undefined,\n });\n\n // If no renderers known, resolve immediately\n if (this.rendererIds.size === 0) {\n return Promise.resolve();\n }\n\n // Request profiling data from each renderer\n for (const rendererID of this.rendererIds) {\n this.sendToAll({\n event: 'getProfilingData',\n payload: { rendererID },\n });\n }\n\n const expected = this.rendererIds.size;\n return new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n this.pendingProfilingCollect = null;\n resolve();\n }, 5000);\n\n this.pendingProfilingCollect = { resolve, timer, remaining: expected };\n });\n }\n\n private handleMessage(ws: WebSocket, msg: DevToolsMessage): void {\n switch (msg.event) {\n case 'backendInitialized':\n // Send the full frontend handshake sequence\n this.sendTo(ws, { event: 'getBridgeProtocol', payload: undefined });\n this.sendTo(ws, { event: 'getBackendVersion', payload: undefined });\n this.sendTo(ws, { event: 'getIfHasUnsupportedRendererVersion', payload: undefined });\n this.sendTo(ws, { event: 'getHookSettings', payload: undefined });\n this.sendTo(ws, { event: 'getProfilingStatus', payload: undefined });\n break;\n\n case 'bridgeProtocol':\n case 'backendVersion':\n case 'profilingStatus':\n case 'overrideComponentFilters':\n break;\n\n case 'operations':\n this.handleOperations(ws, msg.payload as number[]);\n break;\n\n case 'inspectedElement':\n this.handleInspectedElement(msg.payload);\n break;\n\n case 'profilingData':\n this.handleProfilingData(msg.payload);\n break;\n\n case 'renderer': {\n const payload = msg.payload as { id: number };\n this.rendererIds.add(payload.id);\n break;\n }\n\n case 'rendererAttached': {\n const payload = msg.payload as { id: number };\n this.rendererIds.add(payload.id);\n break;\n }\n\n case 'shutdown':\n ws.close();\n break;\n\n // Silently ignore known but unhandled events\n case 'hookSettings':\n case 'isBackendStorageAPISupported':\n case 'isReactNativeEnvironment':\n case 'isReloadAndProfileSupportedByBackend':\n case 'isSynchronousXHRSupported':\n case 'syncSelectionFromNativeElementsPanel':\n case 'unsupportedRendererVersion':\n break;\n\n default:\n break;\n }\n }\n\n private handleOperations(ws: WebSocket, operations: number[]): void {\n if (operations.length >= 2) {\n // Track renderer ID (first element of every operations array)\n this.rendererIds.add(operations[0]);\n\n // Track which root fiber IDs belong to this connection\n const rootFiberId = operations[1];\n let roots = this.connectionRoots.get(ws);\n if (!roots) {\n roots = new Set();\n this.connectionRoots.set(ws, roots);\n }\n roots.add(rootFiberId);\n }\n const added = this.tree.applyOperations(operations);\n\n // Cache display names during profiling so unmounted components are still identifiable\n if (this.profiler.isActive()) {\n for (const node of added) {\n this.profiler.trackComponent(node.id, node.displayName);\n }\n }\n }\n\n private cleanupConnection(ws: WebSocket): void {\n this.connections.delete(ws);\n // Remove all root trees that belonged to this connection\n const roots = this.connectionRoots.get(ws);\n if (roots) {\n for (const rootId of roots) {\n this.tree.removeRoot(rootId);\n }\n this.connectionRoots.delete(ws);\n }\n }\n\n private handleInspectedElement(payload: unknown): void {\n const data = payload as {\n type: string;\n id: number;\n value?: {\n id: number;\n displayName: string;\n type: number;\n key: string | null;\n props: Record<string, unknown>;\n state: Record<string, unknown> | null;\n hooks: unknown[] | null;\n };\n };\n\n if (data.type !== 'full-data' && data.type !== 'hydrated-path') {\n // No data available\n const pending = this.pendingInspections.get(data.id);\n if (pending) {\n clearTimeout(pending.timer);\n this.pendingInspections.delete(data.id);\n pending.resolve(null);\n }\n return;\n }\n\n const pending = this.pendingInspections.get(data.id);\n if (!pending || !data.value) return;\n\n clearTimeout(pending.timer);\n this.pendingInspections.delete(data.id);\n\n const node = this.tree.getNode(data.id);\n const inspected: InspectedElement = {\n id: data.id,\n displayName: data.value.displayName || node?.displayName || 'Unknown',\n type: node?.type || 'other',\n key: data.value.key,\n props: cleanDehydrated(data.value.props) as Record<string, unknown>,\n state: data.value.state\n ? (cleanDehydrated(data.value.state) as Record<string, unknown>)\n : null,\n hooks: data.value.hooks\n ? parseHooks(data.value.hooks)\n : null,\n renderedAt: null,\n };\n\n pending.resolve(inspected);\n }\n\n private handleProfilingData(payload: unknown): void {\n // React DevTools sends profiling data as a complex nested structure.\n // We forward it to the profiler for processing.\n this.profiler.processProfilingData(payload);\n\n // Resolve once all expected renderer responses have arrived\n if (this.pendingProfilingCollect) {\n this.pendingProfilingCollect.remaining--;\n if (this.pendingProfilingCollect.remaining <= 0) {\n clearTimeout(this.pendingProfilingCollect.timer);\n const pending = this.pendingProfilingCollect;\n this.pendingProfilingCollect = null;\n pending.resolve();\n }\n }\n }\n\n private sendTo(ws: WebSocket, msg: DevToolsMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(msg));\n }\n }\n\n private sendToAll(msg: DevToolsMessage): void {\n const raw = JSON.stringify(msg);\n for (const conn of this.connections) {\n if (conn.readyState === WebSocket.OPEN) {\n conn.send(raw);\n }\n }\n }\n}\n\n/**\n * React DevTools uses \"dehydrated\" values for complex objects.\n * These appear as objects with `type: 'string'` and other metadata.\n * We simplify them for display.\n */\nfunction cleanDehydrated(obj: unknown): unknown {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj !== 'object') return obj;\n if (Array.isArray(obj)) return obj.map(cleanDehydrated);\n\n const record = obj as Record<string, unknown>;\n\n // Dehydrated value markers from React DevTools\n if ('type' in record && 'preview_short' in record) {\n return record['preview_short'];\n }\n\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(record)) {\n cleaned[key] = cleanDehydrated(value);\n }\n return cleaned;\n}\n\nfunction parseHooks(hooks: unknown[]): { name: string; value: unknown; subHooks?: { name: string; value: unknown }[] }[] {\n return hooks.map((hook) => {\n const h = hook as {\n id: number | null;\n isStateEditable: boolean;\n name: string;\n value: unknown;\n subHooks?: unknown[];\n };\n const result: { name: string; value: unknown; subHooks?: { name: string; value: unknown }[] } = {\n name: h.name,\n value: cleanDehydrated(h.value),\n };\n if (h.subHooks && h.subHooks.length > 0) {\n result.subHooks = parseHooks(h.subHooks) as { name: string; value: unknown }[];\n }\n return result;\n });\n}\n","import type { ComponentNode, ComponentType } from './types.js';\n\n/**\n * React DevTools operations encoding (protocol v2):\n * Operations is a flat array of numbers representing tree mutations.\n *\n * Format: [rendererID, rootFiberID, stringTableSize, ...stringTable, ...ops]\n *\n * The string table encodes display names and keys. Each entry is:\n * [length, ...charCodes]\n * String ID 0 = null. String ID 1 = first entry, etc.\n *\n * Operation types (from React DevTools source):\n */\nconst TREE_OPERATION_ADD = 1;\nconst TREE_OPERATION_REMOVE = 2;\nconst TREE_OPERATION_REORDER_CHILDREN = 3;\nconst TREE_OPERATION_UPDATE_TREE_BASE_DURATION = 4;\nconst TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS = 5;\nconst TREE_OPERATION_REMOVE_ROOT = 6;\nconst TREE_OPERATION_SET_SUBTREE_MODE = 7;\n\n/**\n * Suspense tree operations (newer React DevTools backends, e.g. browser extension):\n */\nconst SUSPENSE_TREE_OPERATION_ADD = 8;\nconst SUSPENSE_TREE_OPERATION_REMOVE = 9;\nconst SUSPENSE_TREE_OPERATION_REORDER_CHILDREN = 10;\nconst SUSPENSE_TREE_OPERATION_RESIZE = 11;\nconst SUSPENSE_TREE_OPERATION_SUSPENDERS = 12;\nconst TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE = 13;\n\n/**\n * Element types from React DevTools (react-devtools-shared/src/frontend/types.js)\n */\nconst ELEMENT_TYPE_CLASS = 1;\n// const ELEMENT_TYPE_CONTEXT = 2;\nconst ELEMENT_TYPE_FUNCTION = 5;\nconst ELEMENT_TYPE_FORWARD_REF = 6;\nconst ELEMENT_TYPE_HOST = 7;\nconst ELEMENT_TYPE_MEMO = 8;\n// const ELEMENT_TYPE_OTHER = 9;\nconst ELEMENT_TYPE_PROFILER = 10;\nconst ELEMENT_TYPE_ROOT = 11;\nconst ELEMENT_TYPE_SUSPENSE = 12;\n\nfunction toComponentType(elementType: number): ComponentType {\n switch (elementType) {\n case ELEMENT_TYPE_CLASS:\n return 'class';\n case ELEMENT_TYPE_FUNCTION:\n return 'function';\n case ELEMENT_TYPE_FORWARD_REF:\n return 'forwardRef';\n case ELEMENT_TYPE_HOST:\n return 'host';\n case ELEMENT_TYPE_MEMO:\n return 'memo';\n case ELEMENT_TYPE_PROFILER:\n return 'profiler';\n case ELEMENT_TYPE_SUSPENSE:\n return 'suspense';\n case ELEMENT_TYPE_ROOT:\n return 'other'; // roots are internal, map to 'other'\n default:\n return 'other';\n }\n}\n\n/**\n * Skip a variable-length rect encoding in the operations array.\n * Rects are encoded as: count, then count * 4 values (x, y, w, h each × 1000).\n * A count of -1 means null (no rects).\n * Returns the new index after skipping.\n */\nfunction skipRects(operations: number[], i: number): number {\n const count = operations[i++];\n if (count === -1) return i;\n return i + count * 4;\n}\n\nexport interface TreeNode {\n id: number;\n label: string;\n displayName: string;\n type: ComponentType;\n key: string | null;\n parentId: number | null;\n children: number[];\n depth: number;\n}\n\nexport class ComponentTree {\n private nodes = new Map<number, ComponentNode>();\n private roots: number[] = [];\n /** Index: lowercase display name → set of node ids */\n private nameIndex = new Map<string, Set<number>>();\n /** Label → real node ID (e.g., \"@c1\" → 10) */\n private labelToId = new Map<string, number>();\n /** Real node ID → label */\n private idToLabel = new Map<number, string>();\n /**\n * Whether the backend uses the extended ADD format (8 fields with namePropStringID).\n * Auto-detected from the presence of SUSPENSE_TREE_OPERATION opcodes.\n */\n private extendedAddFormat = false;\n\n applyOperations(operations: number[]): Array<{ id: number; displayName: string }> {\n if (operations.length < 2) return [];\n\n const added: Array<{ id: number; displayName: string }> = [];\n const rendererId = operations[0];\n // operations[1] is the root fiber ID\n let i = 2;\n\n // Parse the string table (protocol v2)\n const stringTable: Array<string | null> = [null]; // ID 0 = null\n const stringTableSize = operations[i++];\n const stringTableEnd = i + stringTableSize;\n while (i < stringTableEnd) {\n const strLen = operations[i++];\n let str = '';\n for (let j = 0; j < strLen; j++) {\n str += String.fromCodePoint(operations[i++]);\n }\n stringTable.push(str);\n }\n\n // Parse operations\n while (i < operations.length) {\n const op = operations[i];\n\n switch (op) {\n case TREE_OPERATION_ADD: {\n const id = operations[i + 1];\n const elementType = operations[i + 2];\n i += 3;\n\n if (elementType === ELEMENT_TYPE_ROOT) {\n // Root node: isStrictModeCompliant, supportsProfiling,\n // supportsStrictMode, hasOwnerMetadata\n i += 4;\n\n const node: ComponentNode = {\n id,\n displayName: 'Root',\n type: 'other',\n key: null,\n parentId: null,\n children: [],\n rendererId,\n };\n this.nodes.set(id, node);\n added.push({ id, displayName: node.displayName });\n if (!this.roots.includes(id)) {\n this.roots.push(id);\n }\n } else {\n const parentId = operations[i++];\n i++; // ownerID\n const displayNameStringId = operations[i++];\n const keyStringId = operations[i++];\n if (this.extendedAddFormat) {\n i++; // namePropStringID (added in newer backends)\n }\n\n const displayName =\n (displayNameStringId > 0 ? stringTable[displayNameStringId] : null) ||\n (elementType === ELEMENT_TYPE_HOST ? 'HostComponent' : 'Anonymous');\n const key = keyStringId > 0 ? stringTable[keyStringId] || null : null;\n\n const node: ComponentNode = {\n id,\n displayName,\n type: toComponentType(elementType),\n key,\n parentId: parentId === 0 ? null : parentId,\n children: [],\n rendererId,\n };\n\n this.nodes.set(id, node);\n added.push({ id, displayName });\n\n // Add to parent's children\n if (parentId === 0) {\n if (!this.roots.includes(id)) {\n this.roots.push(id);\n }\n } else {\n const parent = this.nodes.get(parentId);\n if (parent) {\n parent.children.push(id);\n }\n }\n\n // Update name index\n if (displayName) {\n const lower = displayName.toLowerCase();\n let set = this.nameIndex.get(lower);\n if (!set) {\n set = new Set();\n this.nameIndex.set(lower, set);\n }\n set.add(id);\n }\n }\n break;\n }\n\n case TREE_OPERATION_REMOVE: {\n const numRemoved = operations[i + 1];\n for (let j = 0; j < numRemoved; j++) {\n const id = operations[i + 2 + j];\n this.removeNode(id);\n }\n i += 2 + numRemoved;\n break;\n }\n\n case TREE_OPERATION_REORDER_CHILDREN: {\n const id = operations[i + 1];\n const numChildren = operations[i + 2];\n const newChildren: number[] = [];\n for (let j = 0; j < numChildren; j++) {\n newChildren.push(operations[i + 3 + j]);\n }\n const node = this.nodes.get(id);\n if (node) {\n node.children = newChildren;\n }\n i += 3 + numChildren;\n break;\n }\n\n case TREE_OPERATION_UPDATE_TREE_BASE_DURATION: {\n // id, baseDuration — skip\n i += 3;\n break;\n }\n\n case TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS: {\n // id, numErrors, numWarnings\n i += 4;\n break;\n }\n\n case TREE_OPERATION_REMOVE_ROOT: {\n const rootId = operations[i + 1];\n this.removeNode(rootId);\n i += 2;\n break;\n }\n\n case TREE_OPERATION_SET_SUBTREE_MODE: {\n // id, mode\n i += 3;\n break;\n }\n\n // ── Suspense tree operations (newer backends) ──\n\n case SUSPENSE_TREE_OPERATION_ADD: {\n // Presence of suspense ops means the backend also uses 8-field ADD\n this.extendedAddFormat = true;\n // fiberID, parentID, nameStringID, isSuspended, rects\n i += 5; // opcode + 4 fields\n i = skipRects(operations, i);\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_REMOVE: {\n this.extendedAddFormat = true;\n // numIDs, then that many IDs\n const numIds = operations[i + 1];\n i += 2 + numIds;\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_REORDER_CHILDREN: {\n this.extendedAddFormat = true;\n // parentID, numChildren, then that many child IDs\n const numSuspenseChildren = operations[i + 2];\n i += 3 + numSuspenseChildren;\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_RESIZE: {\n this.extendedAddFormat = true;\n // fiberID, rects\n i += 2; // opcode + fiberID\n i = skipRects(operations, i);\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_SUSPENDERS: {\n this.extendedAddFormat = true;\n // numChanges, then numChanges * 4 values\n const numChanges = operations[i + 1];\n i += 2 + numChanges * 4;\n break;\n }\n\n case TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE: {\n this.extendedAddFormat = true;\n // id\n i += 2;\n break;\n }\n\n default:\n // Unknown operation — skip one value and try to continue.\n // Future protocol additions may cause brief misalignment but\n // subsequent operations batches will self-correct.\n i++;\n break;\n }\n }\n\n return added;\n }\n\n private removeNode(id: number): void {\n const node = this.nodes.get(id);\n if (!node) return;\n\n // Remove from parent's children\n if (node.parentId !== null) {\n const parent = this.nodes.get(node.parentId);\n if (parent) {\n parent.children = parent.children.filter((c) => c !== id);\n }\n }\n\n // Remove from roots\n this.roots = this.roots.filter((r) => r !== id);\n\n // Remove from name index\n if (node.displayName) {\n const lower = node.displayName.toLowerCase();\n const set = this.nameIndex.get(lower);\n if (set) {\n set.delete(id);\n if (set.size === 0) this.nameIndex.delete(lower);\n }\n }\n\n // Recursively remove children\n for (const childId of node.children) {\n this.removeNode(childId);\n }\n\n this.nodes.delete(id);\n }\n\n getNode(id: number): ComponentNode | undefined {\n return this.nodes.get(id);\n }\n\n getTree(maxDepth?: number): TreeNode[] {\n const result: TreeNode[] = [];\n\n // Rebuild label maps on every getTree() call\n this.labelToId.clear();\n this.idToLabel.clear();\n let labelCounter = 1;\n\n const walk = (id: number, depth: number) => {\n const node = this.nodes.get(id);\n if (!node) return;\n if (maxDepth !== undefined && depth > maxDepth) return;\n\n const label = `@c${labelCounter++}`;\n this.labelToId.set(label, node.id);\n this.idToLabel.set(node.id, label);\n\n result.push({\n id: node.id,\n label,\n displayName: node.displayName,\n type: node.type,\n key: node.key,\n parentId: node.parentId,\n children: node.children,\n depth,\n });\n\n for (const childId of node.children) {\n walk(childId, depth + 1);\n }\n };\n\n for (const rootId of this.roots) {\n walk(rootId, 0);\n }\n return result;\n }\n\n findByName(name: string, exact?: boolean): TreeNode[] {\n const results: TreeNode[] = [];\n\n if (exact) {\n const lower = name.toLowerCase();\n const ids = this.nameIndex.get(lower);\n if (ids) {\n for (const id of ids) {\n const node = this.nodes.get(id);\n if (node && node.displayName.toLowerCase() === lower) {\n results.push(this.toTreeNode(node));\n }\n }\n }\n } else {\n const lower = name.toLowerCase();\n for (const [indexName, ids] of this.nameIndex) {\n if (indexName.includes(lower)) {\n for (const id of ids) {\n const node = this.nodes.get(id);\n if (node) {\n results.push(this.toTreeNode(node));\n }\n }\n }\n }\n }\n\n return results;\n }\n\n getComponentCount(): number {\n return this.nodes.size;\n }\n\n getCountByType(): Record<string, number> {\n const counts: Record<string, number> = {};\n for (const node of this.nodes.values()) {\n counts[node.type] = (counts[node.type] || 0) + 1;\n }\n return counts;\n }\n\n getAllNodeIds(): number[] {\n return Array.from(this.nodes.keys());\n }\n\n getRootIds(): number[] {\n return [...this.roots];\n }\n\n removeRoot(rootId: number): void {\n this.removeNode(rootId);\n }\n\n /**\n * Resolve a label like \"@c3\" to a real node ID.\n * Returns undefined if label not found.\n */\n resolveLabel(label: string): number | undefined {\n return this.labelToId.get(label);\n }\n\n /**\n * Resolve either a label string (\"@c3\") or a numeric ID to a real node ID.\n */\n resolveId(id: number | string): number | undefined {\n if (typeof id === 'number') return id;\n if (id.startsWith('@c')) return this.labelToId.get(id);\n // Try parsing as number\n const num = parseInt(id, 10);\n return isNaN(num) ? undefined : num;\n }\n\n private toTreeNode(node: ComponentNode): TreeNode {\n // Calculate depth by walking up the tree\n let depth = 0;\n let current = node;\n while (current.parentId !== null) {\n depth++;\n const parent = this.nodes.get(current.parentId);\n if (!parent) break;\n current = parent;\n }\n\n return {\n id: node.id,\n label: this.idToLabel.get(node.id) || `@c?`,\n displayName: node.displayName,\n type: node.type,\n key: node.key,\n parentId: node.parentId,\n children: node.children,\n depth,\n };\n }\n}\n","import type {\n ProfilingSession,\n ProfilingCommit,\n ChangeDescription,\n ComponentRenderReport,\n RenderCause,\n} from './types.js';\nimport type { ComponentTree } from './component-tree.js';\n\nexport interface ProfileSummary {\n name: string;\n duration: number;\n commitCount: number;\n componentRenderCounts: { id: number; displayName: string; count: number }[];\n}\n\nexport interface TimelineEntry {\n index: number;\n timestamp: number;\n duration: number;\n componentCount: number;\n}\n\nexport interface CommitDetail {\n index: number;\n timestamp: number;\n duration: number;\n components: Array<{\n id: number;\n displayName: string;\n actualDuration: number;\n selfDuration: number;\n causes: RenderCause[];\n }>;\n totalComponents: number;\n}\n\nexport class Profiler {\n private session: ProfilingSession | null = null;\n /** Display names captured during profiling (survives unmounts) */\n private displayNames = new Map<number, string>();\n\n isActive(): boolean {\n return this.session !== null && this.session.stoppedAt === null;\n }\n\n start(name?: string): void {\n this.displayNames.clear();\n this.session = {\n name: name || `session-${Date.now()}`,\n startedAt: Date.now(),\n stoppedAt: null,\n commits: [],\n };\n }\n\n /** Cache a component's display name (call during profiling to survive unmounts) */\n trackComponent(id: number, displayName: string): void {\n this.displayNames.set(id, displayName);\n }\n\n stop(tree?: ComponentTree): ProfileSummary | null {\n if (!this.session) return null;\n this.session.stoppedAt = Date.now();\n\n const duration = this.session.stoppedAt - this.session.startedAt;\n\n // Count renders per component\n const renderCounts = new Map<number, number>();\n for (const commit of this.session.commits) {\n for (const [id] of commit.fiberActualDurations) {\n renderCounts.set(id, (renderCounts.get(id) || 0) + 1);\n }\n }\n\n const componentRenderCounts = Array.from(renderCounts.entries())\n .map(([id, count]) => ({\n id,\n displayName: tree?.getNode(id)?.displayName || this.displayNames.get(id) || '',\n count,\n }))\n .sort((a, b) => b.count - a.count);\n\n return {\n name: this.session.name,\n duration,\n commitCount: this.session.commits.length,\n componentRenderCounts,\n };\n }\n\n /**\n * Process profiling data sent from React DevTools.\n *\n * The data format varies between React versions. We handle the common\n * format where each commit contains:\n * - commitTime\n * - duration\n * - fiberActualDurations: [id, duration, ...]\n * - fiberSelfDurations: [id, duration, ...]\n * - changeDescriptions: Map<id, description>\n */\n processProfilingData(payload: unknown): void {\n if (!this.session || this.session.stoppedAt !== null) return;\n\n const data = payload as {\n dataForRoots?: Array<{\n commitData?: Array<{\n changeDescriptions?: Array<[number, unknown]> | Map<number, unknown>;\n duration?: number;\n fiberActualDurations?: Array<[number, number]> | number[];\n fiberSelfDurations?: Array<[number, number]> | number[];\n timestamp?: number;\n }>;\n operations?: unknown[];\n }>;\n // Alternative flat format\n commitData?: Array<{\n changeDescriptions?: Array<[number, unknown]> | Map<number, unknown>;\n duration?: number;\n fiberActualDurations?: Array<[number, number]> | number[];\n fiberSelfDurations?: Array<[number, number]> | number[];\n timestamp?: number;\n }>;\n };\n\n // Handle nested format (dataForRoots)\n const roots = data?.dataForRoots;\n if (roots) {\n for (const root of roots) {\n if (root.commitData) {\n for (const commitData of root.commitData) {\n this.processCommitData(commitData);\n }\n }\n }\n return;\n }\n\n // Handle flat format\n if (data?.commitData) {\n for (const commitData of data.commitData) {\n this.processCommitData(commitData);\n }\n }\n }\n\n private processCommitData(commitData: {\n changeDescriptions?: Array<[number, unknown]> | Map<number, unknown>;\n duration?: number;\n fiberActualDurations?: Array<[number, number]> | number[];\n fiberSelfDurations?: Array<[number, number]> | number[];\n timestamp?: number;\n }): void {\n const commit: ProfilingCommit = {\n timestamp: commitData.timestamp || Date.now(),\n duration: commitData.duration || 0,\n fiberActualDurations: new Map(),\n fiberSelfDurations: new Map(),\n changeDescriptions: new Map(),\n };\n\n // Parse fiber durations (can be [id, duration, id, duration, ...] or [[id, duration], ...])\n if (commitData.fiberActualDurations) {\n parseDurations(commitData.fiberActualDurations, commit.fiberActualDurations);\n }\n if (commitData.fiberSelfDurations) {\n parseDurations(commitData.fiberSelfDurations, commit.fiberSelfDurations);\n }\n\n // Parse change descriptions\n if (commitData.changeDescriptions) {\n const entries =\n commitData.changeDescriptions instanceof Map\n ? commitData.changeDescriptions.entries()\n : commitData.changeDescriptions[Symbol.iterator]();\n for (const [id, desc] of entries) {\n const d = desc as {\n didHooksChange?: boolean;\n isFirstMount?: boolean;\n props?: string[] | null;\n state?: string[] | null;\n hooks?: number[] | null;\n };\n commit.changeDescriptions.set(id as number, {\n didHooksChange: d.didHooksChange || false,\n isFirstMount: d.isFirstMount || false,\n props: d.props || null,\n state: d.state || null,\n hooks: d.hooks || null,\n });\n }\n }\n\n this.session!.commits.push(commit);\n }\n\n getReport(\n componentId: number,\n tree: ComponentTree,\n ): ComponentRenderReport | null {\n if (!this.session) return null;\n\n const node = tree.getNode(componentId);\n let renderCount = 0;\n let totalDuration = 0;\n let maxDuration = 0;\n const causeSet = new Set<RenderCause>();\n\n for (const commit of this.session.commits) {\n const duration = commit.fiberActualDurations.get(componentId);\n if (duration !== undefined) {\n renderCount++;\n totalDuration += duration;\n if (duration > maxDuration) maxDuration = duration;\n\n const desc = commit.changeDescriptions.get(componentId);\n if (desc) {\n for (const cause of describeCauses(desc)) {\n causeSet.add(cause);\n }\n }\n }\n }\n\n if (renderCount === 0) return null;\n\n return {\n id: componentId,\n displayName: node?.displayName || this.displayNames.get(componentId) || `Component#${componentId}`,\n renderCount,\n totalDuration,\n avgDuration: totalDuration / renderCount,\n maxDuration,\n causes: Array.from(causeSet),\n };\n }\n\n getSlowest(\n tree: ComponentTree,\n limit = 10,\n ): ComponentRenderReport[] {\n return this.getAllReports(tree)\n .sort((a, b) => b.avgDuration - a.avgDuration)\n .slice(0, limit);\n }\n\n getMostRerenders(\n tree: ComponentTree,\n limit = 10,\n ): ComponentRenderReport[] {\n return this.getAllReports(tree)\n .sort((a, b) => b.renderCount - a.renderCount)\n .slice(0, limit);\n }\n\n getCommitDetails(index: number, tree: ComponentTree, limit = 10): CommitDetail | null {\n if (!this.session) return null;\n if (index < 0 || index >= this.session.commits.length) return null;\n\n const commit = this.session.commits[index];\n const components: CommitDetail['components'] = [];\n\n for (const [id, actualDuration] of commit.fiberActualDurations) {\n const selfDuration = commit.fiberSelfDurations.get(id) || 0;\n const desc = commit.changeDescriptions.get(id);\n components.push({\n id,\n displayName: tree.getNode(id)?.displayName || this.displayNames.get(id) || `Component#${id}`,\n actualDuration,\n selfDuration,\n causes: desc ? describeCauses(desc) : [],\n });\n }\n\n components.sort((a, b) => b.selfDuration - a.selfDuration);\n\n const totalCount = components.length;\n\n return {\n index,\n timestamp: commit.timestamp,\n duration: commit.duration,\n components: limit > 0 ? components.slice(0, limit) : components,\n totalComponents: totalCount,\n };\n }\n\n getTimeline(limit?: number): TimelineEntry[] {\n if (!this.session) return [];\n\n const entries = this.session.commits.map((commit, index) => ({\n index,\n timestamp: commit.timestamp,\n duration: commit.duration,\n componentCount: commit.fiberActualDurations.size,\n }));\n\n if (limit) return entries.slice(0, limit);\n return entries;\n }\n\n private getAllReports(tree: ComponentTree): ComponentRenderReport[] {\n if (!this.session) return [];\n\n // Collect all component IDs that appear in profiling data\n const componentIds = new Set<number>();\n for (const commit of this.session.commits) {\n for (const id of commit.fiberActualDurations.keys()) {\n componentIds.add(id);\n }\n }\n\n const reports: ComponentRenderReport[] = [];\n for (const id of componentIds) {\n const report = this.getReport(id, tree);\n if (report) reports.push(report);\n }\n return reports;\n }\n}\n\nfunction parseDurations(\n raw: Array<[number, number]> | number[],\n target: Map<number, number>,\n): void {\n if (raw.length === 0) return;\n\n // Check if it's array of tuples or flat array\n if (Array.isArray(raw[0])) {\n // [[id, duration], ...]\n for (const [id, duration] of raw as Array<[number, number]>) {\n target.set(id, duration);\n }\n } else {\n // [id, duration, id, duration, ...]\n const flat = raw as number[];\n for (let i = 0; i < flat.length; i += 2) {\n target.set(flat[i], flat[i + 1]);\n }\n }\n}\n\nfunction describeCauses(desc: ChangeDescription): RenderCause[] {\n const causes: RenderCause[] = [];\n if (desc.isFirstMount) {\n causes.push('first-mount');\n return causes;\n }\n if (desc.props && desc.props.length > 0) causes.push('props-changed');\n if (desc.state && desc.state.length > 0) causes.push('state-changed');\n if (desc.didHooksChange) causes.push('hooks-changed');\n // If no specific cause found, it was likely parent-triggered\n if (causes.length === 0) causes.push('parent-rendered');\n return causes;\n}\n"],"mappings":"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","names":["port","pending","port"]}
1
+ {"version":3,"sources":["../src/daemon.ts","../src/devtools-bridge.ts","../src/component-tree.ts","../src/profiler.ts"],"sourcesContent":["import net from 'node:net';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { DevToolsBridge } from './devtools-bridge.js';\nimport { ComponentTree } from './component-tree.js';\nimport { Profiler } from './profiler.js';\nimport type { IpcCommand, IpcResponse, DaemonInfo, StatusInfo } from './types.js';\n\nconst DEFAULT_STATE_DIR = path.join(\n process.env.HOME || process.env.USERPROFILE || '/tmp',\n '.agent-react-devtools',\n);\n\nlet STATE_DIR = DEFAULT_STATE_DIR;\n\nfunction getSocketPath(): string {\n return path.join(STATE_DIR, 'daemon.sock');\n}\n\nfunction getDaemonInfoPath(): string {\n return path.join(STATE_DIR, 'daemon.json');\n}\n\n/**\n * Enrich profiling result items with label + type from the component tree.\n */\nfunction enrichWithLabels(\n items: Array<{ id: number; label?: string; type?: string }>,\n tree: ComponentTree,\n): void {\n for (const item of items) {\n if (!item.label) item.label = tree.getLabel(item.id);\n if (!item.type) {\n const node = tree.getNode(item.id);\n if (node) item.type = node.type;\n }\n }\n}\n\nclass Daemon {\n private ipcServer: net.Server | null = null;\n private bridge: DevToolsBridge;\n private tree: ComponentTree;\n private profiler: Profiler;\n private port: number;\n private startedAt = Date.now();\n\n constructor(port: number) {\n this.port = port;\n this.tree = new ComponentTree();\n this.profiler = new Profiler();\n this.bridge = new DevToolsBridge(port, this.tree, this.profiler);\n }\n\n async start(): Promise<void> {\n // Ensure state directory exists\n fs.mkdirSync(STATE_DIR, { recursive: true });\n\n // Clean up stale socket\n const socketPath = getSocketPath();\n if (fs.existsSync(socketPath)) {\n try {\n fs.unlinkSync(socketPath);\n } catch {\n // ignore\n }\n }\n\n // Start WebSocket bridge\n await this.bridge.start();\n\n // Start IPC server\n await this.startIpc(socketPath);\n\n // Write daemon info\n const info: DaemonInfo = {\n pid: process.pid,\n port: this.port,\n socketPath,\n startedAt: this.startedAt,\n };\n fs.writeFileSync(getDaemonInfoPath(), JSON.stringify(info, null, 2));\n\n console.log(`Daemon started (pid=${process.pid}, port=${this.port})`);\n\n // Handle shutdown\n const shutdown = () => {\n this.stop();\n process.exit(0);\n };\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n }\n\n private startIpc(socketPath: string): Promise<void> {\n return new Promise((resolve, reject) => {\n this.ipcServer = net.createServer((conn) => {\n let buffer = '';\n\n conn.on('data', (chunk) => {\n buffer += chunk.toString();\n\n // Process complete messages (newline-delimited JSON)\n let newlineIdx: number;\n while ((newlineIdx = buffer.indexOf('\\n')) !== -1) {\n const line = buffer.slice(0, newlineIdx);\n buffer = buffer.slice(newlineIdx + 1);\n\n try {\n const cmd: IpcCommand = JSON.parse(line);\n this.handleCommand(cmd).then((response) => {\n conn.write(JSON.stringify(response) + '\\n');\n });\n } catch {\n const response: IpcResponse = {\n ok: false,\n error: 'Invalid JSON',\n };\n conn.write(JSON.stringify(response) + '\\n');\n }\n }\n });\n });\n\n this.ipcServer.on('error', reject);\n\n this.ipcServer.listen(socketPath, () => {\n resolve();\n });\n });\n }\n\n private async handleCommand(cmd: IpcCommand): Promise<IpcResponse> {\n try {\n switch (cmd.type) {\n case 'ping':\n return { ok: true, data: 'pong' };\n\n case 'status':\n return {\n ok: true,\n data: {\n daemonRunning: true,\n port: this.port,\n connectedApps: this.bridge.getConnectedAppCount(),\n componentCount: this.tree.getComponentCount(),\n profilingActive: this.profiler.isActive(),\n uptime: Date.now() - this.startedAt,\n } satisfies StatusInfo,\n };\n\n case 'get-tree':\n return {\n ok: true,\n data: this.tree.getTree(cmd.depth),\n };\n\n case 'get-component': {\n const resolvedId = this.tree.resolveId(cmd.id);\n if (resolvedId === undefined) {\n return { ok: false, error: `Component ${cmd.id} not found` };\n }\n const element = await this.bridge.inspectElement(resolvedId);\n if (!element) {\n return { ok: false, error: `Component ${cmd.id} not found` };\n }\n // Include the label if the request used one\n const label = typeof cmd.id === 'string' ? cmd.id : undefined;\n return { ok: true, data: element, label };\n }\n\n case 'find':\n return {\n ok: true,\n data: this.tree.findByName(cmd.name, cmd.exact),\n };\n\n case 'count':\n return {\n ok: true,\n data: this.tree.getCountByType(),\n };\n\n case 'profile-start':\n this.profiler.start(cmd.name);\n // Snapshot existing component names so they survive unmounts\n for (const id of this.tree.getAllNodeIds()) {\n const node = this.tree.getNode(id);\n if (node) this.profiler.trackComponent(id, node.displayName);\n }\n this.bridge.startProfiling();\n return { ok: true, data: 'Profiling started' };\n\n case 'profile-stop': {\n await this.bridge.stopProfilingAndCollect();\n const session = this.profiler.stop(this.tree);\n if (!session) {\n return { ok: false, error: 'No active profiling session' };\n }\n enrichWithLabels(session.componentRenderCounts, this.tree);\n return { ok: true, data: session };\n }\n\n case 'profile-report': {\n const resolvedCompId = this.tree.resolveId(cmd.componentId);\n if (resolvedCompId === undefined) {\n return { ok: false, error: `Component ${cmd.componentId} not found` };\n }\n const report = this.profiler.getReport(resolvedCompId, this.tree);\n if (!report) {\n return {\n ok: false,\n error: `No profiling data for component ${cmd.componentId}`,\n };\n }\n enrichWithLabels([report], this.tree);\n const compLabel = typeof cmd.componentId === 'string' ? cmd.componentId : undefined;\n return { ok: true, data: report, label: compLabel };\n }\n\n case 'profile-slow': {\n const slowest = this.profiler.getSlowest(this.tree, cmd.limit);\n enrichWithLabels(slowest, this.tree);\n return { ok: true, data: slowest };\n }\n\n case 'profile-rerenders': {\n const rerenders = this.profiler.getMostRerenders(this.tree, cmd.limit);\n enrichWithLabels(rerenders, this.tree);\n return { ok: true, data: rerenders };\n }\n\n case 'profile-timeline':\n return {\n ok: true,\n data: this.profiler.getTimeline(cmd.limit),\n };\n\n case 'profile-commit': {\n const detail = this.profiler.getCommitDetails(cmd.index, this.tree, cmd.limit);\n if (!detail) {\n return { ok: false, error: `Commit #${cmd.index} not found` };\n }\n enrichWithLabels(detail.components, this.tree);\n return { ok: true, data: detail };\n }\n\n default:\n return { ok: false, error: `Unknown command: ${(cmd as any).type}` };\n }\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n stop(): void {\n this.bridge.stop();\n if (this.ipcServer) {\n this.ipcServer.close();\n this.ipcServer = null;\n }\n // Clean up files\n try {\n fs.unlinkSync(getSocketPath());\n } catch {\n // ignore\n }\n try {\n fs.unlinkSync(getDaemonInfoPath());\n } catch {\n // ignore\n }\n console.log('Daemon stopped');\n }\n}\n\n// ── Main ──\n\nconst portArg = process.argv.find((a) => a.startsWith('--port='));\nconst port = portArg ? parseInt(portArg.split('=')[1], 10) : 8097;\n\nconst stateDirArg = process.argv.find((a) => a.startsWith('--state-dir='));\nif (stateDirArg) {\n STATE_DIR = stateDirArg.split('=')[1];\n}\n\nconst daemon = new Daemon(port);\ndaemon.start().catch((err) => {\n console.error('Failed to start daemon:', err);\n process.exit(1);\n});\n","import { WebSocketServer, WebSocket } from 'ws';\nimport type { ComponentTree } from './component-tree.js';\nimport type { Profiler } from './profiler.js';\nimport type { InspectedElement } from './types.js';\n\n/**\n * React DevTools protocol bridge.\n *\n * Implements the \"Wall\" messaging pattern that React DevTools uses:\n * - The backend (inside React app) sends operations, profiling data, etc.\n * - The frontend (us) can request element inspection, start/stop profiling, etc.\n *\n * Message format over WebSocket:\n * { event: string, payload: any }\n */\n\ninterface DevToolsMessage {\n event: string;\n payload: unknown;\n}\n\ninterface PendingInspection {\n resolve: (value: InspectedElement | null) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\ninterface PendingProfilingCollect {\n resolve: () => void;\n timer: ReturnType<typeof setTimeout>;\n remaining: number;\n}\n\nexport class DevToolsBridge {\n private wss: WebSocketServer | null = null;\n private connections = new Set<WebSocket>();\n private port: number;\n private tree: ComponentTree;\n private profiler: Profiler;\n private pendingInspections = new Map<number, PendingInspection>();\n private pendingProfilingCollect: PendingProfilingCollect | null = null;\n private rendererIds = new Set<number>();\n /** Track which root fiber IDs belong to each WebSocket connection */\n private connectionRoots = new Map<WebSocket, Set<number>>();\n\n constructor(port: number, tree: ComponentTree, profiler: Profiler) {\n this.port = port;\n this.tree = tree;\n this.profiler = profiler;\n }\n\n async start(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.wss = new WebSocketServer({ port: this.port }, () => {\n resolve();\n });\n\n this.wss.on('error', (err) => {\n reject(err);\n });\n\n this.wss.on('connection', (ws) => {\n this.connections.add(ws);\n\n ws.on('message', (data) => {\n try {\n const msg: DevToolsMessage = JSON.parse(data.toString());\n this.handleMessage(ws, msg);\n } catch {\n // ignore parse errors\n }\n });\n\n ws.on('close', () => {\n this.cleanupConnection(ws);\n });\n\n ws.on('error', () => {\n this.cleanupConnection(ws);\n });\n });\n });\n }\n\n stop(): void {\n for (const conn of this.connections) {\n conn.close();\n }\n this.connections.clear();\n if (this.wss) {\n this.wss.close();\n this.wss = null;\n }\n }\n\n getConnectedAppCount(): number {\n return this.connections.size;\n }\n\n /**\n * Request detailed inspection of a specific element.\n * Sends a request to the React app and waits for the response.\n */\n inspectElement(id: number): Promise<InspectedElement | null> {\n const node = this.tree.getNode(id);\n if (!node) return Promise.resolve(null);\n\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n this.pendingInspections.delete(id);\n resolve(null);\n }, 5000);\n\n this.pendingInspections.set(id, { resolve, timer });\n\n this.sendToAll({\n event: 'inspectElement',\n payload: {\n id,\n rendererID: node.rendererId,\n forceFullData: true,\n requestID: id,\n path: null,\n },\n });\n });\n }\n\n startProfiling(): void {\n this.sendToAll({\n event: 'startProfiling',\n payload: { recordChangeDescriptions: true },\n });\n }\n\n /**\n * Stop profiling and request data from each renderer.\n * Returns a promise that resolves when profilingData arrives (or 5s timeout).\n */\n stopProfilingAndCollect(): Promise<void> {\n this.sendToAll({\n event: 'stopProfiling',\n payload: undefined,\n });\n\n // If no renderers known, resolve immediately\n if (this.rendererIds.size === 0) {\n return Promise.resolve();\n }\n\n // Request profiling data from each renderer\n for (const rendererID of this.rendererIds) {\n this.sendToAll({\n event: 'getProfilingData',\n payload: { rendererID },\n });\n }\n\n const expected = this.rendererIds.size;\n return new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n this.pendingProfilingCollect = null;\n resolve();\n }, 5000);\n\n this.pendingProfilingCollect = { resolve, timer, remaining: expected };\n });\n }\n\n private handleMessage(ws: WebSocket, msg: DevToolsMessage): void {\n switch (msg.event) {\n case 'backendInitialized':\n // Send the full frontend handshake sequence\n this.sendTo(ws, { event: 'getBridgeProtocol', payload: undefined });\n this.sendTo(ws, { event: 'getBackendVersion', payload: undefined });\n this.sendTo(ws, { event: 'getIfHasUnsupportedRendererVersion', payload: undefined });\n this.sendTo(ws, { event: 'getHookSettings', payload: undefined });\n this.sendTo(ws, { event: 'getProfilingStatus', payload: undefined });\n break;\n\n case 'bridgeProtocol':\n case 'backendVersion':\n case 'profilingStatus':\n case 'overrideComponentFilters':\n break;\n\n case 'operations':\n this.handleOperations(ws, msg.payload as number[]);\n break;\n\n case 'inspectedElement':\n this.handleInspectedElement(msg.payload);\n break;\n\n case 'profilingData':\n this.handleProfilingData(msg.payload);\n break;\n\n case 'renderer': {\n const payload = msg.payload as { id: number };\n this.rendererIds.add(payload.id);\n break;\n }\n\n case 'rendererAttached': {\n const payload = msg.payload as { id: number };\n this.rendererIds.add(payload.id);\n break;\n }\n\n case 'shutdown':\n ws.close();\n break;\n\n // Silently ignore known but unhandled events\n case 'hookSettings':\n case 'isBackendStorageAPISupported':\n case 'isReactNativeEnvironment':\n case 'isReloadAndProfileSupportedByBackend':\n case 'isSynchronousXHRSupported':\n case 'syncSelectionFromNativeElementsPanel':\n case 'unsupportedRendererVersion':\n break;\n\n default:\n break;\n }\n }\n\n private handleOperations(ws: WebSocket, operations: number[]): void {\n if (operations.length >= 2) {\n // Track renderer ID (first element of every operations array)\n this.rendererIds.add(operations[0]);\n\n // Track which root fiber IDs belong to this connection\n const rootFiberId = operations[1];\n let roots = this.connectionRoots.get(ws);\n if (!roots) {\n roots = new Set();\n this.connectionRoots.set(ws, roots);\n }\n roots.add(rootFiberId);\n }\n const added = this.tree.applyOperations(operations);\n\n // Cache display names during profiling so unmounted components are still identifiable\n if (this.profiler.isActive()) {\n for (const node of added) {\n this.profiler.trackComponent(node.id, node.displayName);\n }\n }\n }\n\n private cleanupConnection(ws: WebSocket): void {\n this.connections.delete(ws);\n // Remove all root trees that belonged to this connection\n const roots = this.connectionRoots.get(ws);\n if (roots) {\n for (const rootId of roots) {\n this.tree.removeRoot(rootId);\n }\n this.connectionRoots.delete(ws);\n }\n }\n\n private handleInspectedElement(payload: unknown): void {\n const data = payload as {\n type: string;\n id: number;\n value?: {\n id: number;\n displayName: string;\n type: number;\n key: string | null;\n props: Record<string, unknown>;\n state: Record<string, unknown> | null;\n hooks: unknown[] | null;\n };\n };\n\n if (data.type !== 'full-data' && data.type !== 'hydrated-path') {\n // No data available\n const pending = this.pendingInspections.get(data.id);\n if (pending) {\n clearTimeout(pending.timer);\n this.pendingInspections.delete(data.id);\n pending.resolve(null);\n }\n return;\n }\n\n const pending = this.pendingInspections.get(data.id);\n if (!pending || !data.value) return;\n\n clearTimeout(pending.timer);\n this.pendingInspections.delete(data.id);\n\n const node = this.tree.getNode(data.id);\n const inspected: InspectedElement = {\n id: data.id,\n displayName: data.value.displayName || node?.displayName || 'Unknown',\n type: node?.type || 'other',\n key: data.value.key,\n props: cleanDehydrated(data.value.props) as Record<string, unknown>,\n state: data.value.state\n ? (cleanDehydrated(data.value.state) as Record<string, unknown>)\n : null,\n hooks: data.value.hooks\n ? parseHooks(data.value.hooks)\n : null,\n renderedAt: null,\n };\n\n pending.resolve(inspected);\n }\n\n private handleProfilingData(payload: unknown): void {\n // React DevTools sends profiling data as a complex nested structure.\n // We forward it to the profiler for processing.\n this.profiler.processProfilingData(payload);\n\n // Resolve once all expected renderer responses have arrived\n if (this.pendingProfilingCollect) {\n this.pendingProfilingCollect.remaining--;\n if (this.pendingProfilingCollect.remaining <= 0) {\n clearTimeout(this.pendingProfilingCollect.timer);\n const pending = this.pendingProfilingCollect;\n this.pendingProfilingCollect = null;\n pending.resolve();\n }\n }\n }\n\n private sendTo(ws: WebSocket, msg: DevToolsMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(msg));\n }\n }\n\n private sendToAll(msg: DevToolsMessage): void {\n const raw = JSON.stringify(msg);\n for (const conn of this.connections) {\n if (conn.readyState === WebSocket.OPEN) {\n conn.send(raw);\n }\n }\n }\n}\n\n/**\n * React DevTools uses \"dehydrated\" values for complex objects.\n * These appear as objects with `type: 'string'` and other metadata.\n * We simplify them for display.\n */\nfunction cleanDehydrated(obj: unknown): unknown {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj !== 'object') return obj;\n if (Array.isArray(obj)) return obj.map(cleanDehydrated);\n\n const record = obj as Record<string, unknown>;\n\n // Dehydrated value markers from React DevTools\n if ('type' in record && 'preview_short' in record) {\n return record['preview_short'];\n }\n\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(record)) {\n cleaned[key] = cleanDehydrated(value);\n }\n return cleaned;\n}\n\nfunction parseHooks(hooks: unknown[]): { name: string; value: unknown; subHooks?: { name: string; value: unknown }[] }[] {\n return hooks.map((hook) => {\n const h = hook as {\n id: number | null;\n isStateEditable: boolean;\n name: string;\n value: unknown;\n subHooks?: unknown[];\n };\n const result: { name: string; value: unknown; subHooks?: { name: string; value: unknown }[] } = {\n name: h.name,\n value: cleanDehydrated(h.value),\n };\n if (h.subHooks && h.subHooks.length > 0) {\n result.subHooks = parseHooks(h.subHooks) as { name: string; value: unknown }[];\n }\n return result;\n });\n}\n","import type { ComponentNode, ComponentType } from './types.js';\n\n/**\n * React DevTools operations encoding (protocol v2):\n * Operations is a flat array of numbers representing tree mutations.\n *\n * Format: [rendererID, rootFiberID, stringTableSize, ...stringTable, ...ops]\n *\n * The string table encodes display names and keys. Each entry is:\n * [length, ...charCodes]\n * String ID 0 = null. String ID 1 = first entry, etc.\n *\n * Operation types (from React DevTools source):\n */\nconst TREE_OPERATION_ADD = 1;\nconst TREE_OPERATION_REMOVE = 2;\nconst TREE_OPERATION_REORDER_CHILDREN = 3;\nconst TREE_OPERATION_UPDATE_TREE_BASE_DURATION = 4;\nconst TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS = 5;\nconst TREE_OPERATION_REMOVE_ROOT = 6;\nconst TREE_OPERATION_SET_SUBTREE_MODE = 7;\n\n/**\n * Suspense tree operations (newer React DevTools backends, e.g. browser extension):\n */\nconst SUSPENSE_TREE_OPERATION_ADD = 8;\nconst SUSPENSE_TREE_OPERATION_REMOVE = 9;\nconst SUSPENSE_TREE_OPERATION_REORDER_CHILDREN = 10;\nconst SUSPENSE_TREE_OPERATION_RESIZE = 11;\nconst SUSPENSE_TREE_OPERATION_SUSPENDERS = 12;\nconst TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE = 13;\n\n/**\n * Element types from React DevTools (react-devtools-shared/src/frontend/types.js)\n */\nconst ELEMENT_TYPE_CLASS = 1;\n// const ELEMENT_TYPE_CONTEXT = 2;\nconst ELEMENT_TYPE_FUNCTION = 5;\nconst ELEMENT_TYPE_FORWARD_REF = 6;\nconst ELEMENT_TYPE_HOST = 7;\nconst ELEMENT_TYPE_MEMO = 8;\n// const ELEMENT_TYPE_OTHER = 9;\nconst ELEMENT_TYPE_PROFILER = 10;\nconst ELEMENT_TYPE_ROOT = 11;\nconst ELEMENT_TYPE_SUSPENSE = 12;\n\nfunction toComponentType(elementType: number): ComponentType {\n switch (elementType) {\n case ELEMENT_TYPE_CLASS:\n return 'class';\n case ELEMENT_TYPE_FUNCTION:\n return 'function';\n case ELEMENT_TYPE_FORWARD_REF:\n return 'forwardRef';\n case ELEMENT_TYPE_HOST:\n return 'host';\n case ELEMENT_TYPE_MEMO:\n return 'memo';\n case ELEMENT_TYPE_PROFILER:\n return 'profiler';\n case ELEMENT_TYPE_SUSPENSE:\n return 'suspense';\n case ELEMENT_TYPE_ROOT:\n return 'other'; // roots are internal, map to 'other'\n default:\n return 'other';\n }\n}\n\n/**\n * Skip a variable-length rect encoding in the operations array.\n * Rects are encoded as: count, then count * 4 values (x, y, w, h each × 1000).\n * A count of -1 means null (no rects).\n * Returns the new index after skipping.\n */\nfunction skipRects(operations: number[], i: number): number {\n const count = operations[i++];\n if (count === -1) return i;\n return i + count * 4;\n}\n\nexport interface TreeNode {\n id: number;\n label: string;\n displayName: string;\n type: ComponentType;\n key: string | null;\n parentId: number | null;\n children: number[];\n depth: number;\n}\n\nexport class ComponentTree {\n private nodes = new Map<number, ComponentNode>();\n private roots: number[] = [];\n /** Index: lowercase display name → set of node ids */\n private nameIndex = new Map<string, Set<number>>();\n /** Label → real node ID (e.g., \"@c1\" → 10) */\n private labelToId = new Map<string, number>();\n /** Real node ID → label */\n private idToLabel = new Map<number, string>();\n /**\n * Whether the backend uses the extended ADD format (8 fields with namePropStringID).\n * Auto-detected from the presence of SUSPENSE_TREE_OPERATION opcodes.\n */\n private extendedAddFormat = false;\n\n applyOperations(operations: number[]): Array<{ id: number; displayName: string }> {\n if (operations.length < 2) return [];\n\n const added: Array<{ id: number; displayName: string }> = [];\n const rendererId = operations[0];\n // operations[1] is the root fiber ID\n let i = 2;\n\n // Parse the string table (protocol v2)\n const stringTable: Array<string | null> = [null]; // ID 0 = null\n const stringTableSize = operations[i++];\n const stringTableEnd = i + stringTableSize;\n while (i < stringTableEnd) {\n const strLen = operations[i++];\n let str = '';\n for (let j = 0; j < strLen; j++) {\n str += String.fromCodePoint(operations[i++]);\n }\n stringTable.push(str);\n }\n\n // Parse operations\n while (i < operations.length) {\n const op = operations[i];\n\n switch (op) {\n case TREE_OPERATION_ADD: {\n const id = operations[i + 1];\n const elementType = operations[i + 2];\n i += 3;\n\n if (elementType === ELEMENT_TYPE_ROOT) {\n // Root node: isStrictModeCompliant, supportsProfiling,\n // supportsStrictMode, hasOwnerMetadata\n i += 4;\n\n const node: ComponentNode = {\n id,\n displayName: 'Root',\n type: 'other',\n key: null,\n parentId: null,\n children: [],\n rendererId,\n };\n this.nodes.set(id, node);\n added.push({ id, displayName: node.displayName });\n if (!this.roots.includes(id)) {\n this.roots.push(id);\n }\n } else {\n const parentId = operations[i++];\n i++; // ownerID\n const displayNameStringId = operations[i++];\n const keyStringId = operations[i++];\n if (this.extendedAddFormat) {\n i++; // namePropStringID (added in newer backends)\n }\n\n const displayName =\n (displayNameStringId > 0 ? stringTable[displayNameStringId] : null) ||\n (elementType === ELEMENT_TYPE_HOST ? 'HostComponent' : 'Anonymous');\n const key = keyStringId > 0 ? stringTable[keyStringId] || null : null;\n\n const node: ComponentNode = {\n id,\n displayName,\n type: toComponentType(elementType),\n key,\n parentId: parentId === 0 ? null : parentId,\n children: [],\n rendererId,\n };\n\n this.nodes.set(id, node);\n added.push({ id, displayName });\n\n // Add to parent's children\n if (parentId === 0) {\n if (!this.roots.includes(id)) {\n this.roots.push(id);\n }\n } else {\n const parent = this.nodes.get(parentId);\n if (parent) {\n parent.children.push(id);\n }\n }\n\n // Update name index\n if (displayName) {\n const lower = displayName.toLowerCase();\n let set = this.nameIndex.get(lower);\n if (!set) {\n set = new Set();\n this.nameIndex.set(lower, set);\n }\n set.add(id);\n }\n }\n break;\n }\n\n case TREE_OPERATION_REMOVE: {\n const numRemoved = operations[i + 1];\n for (let j = 0; j < numRemoved; j++) {\n const id = operations[i + 2 + j];\n this.removeNode(id);\n }\n i += 2 + numRemoved;\n break;\n }\n\n case TREE_OPERATION_REORDER_CHILDREN: {\n const id = operations[i + 1];\n const numChildren = operations[i + 2];\n const newChildren: number[] = [];\n for (let j = 0; j < numChildren; j++) {\n newChildren.push(operations[i + 3 + j]);\n }\n const node = this.nodes.get(id);\n if (node) {\n node.children = newChildren;\n }\n i += 3 + numChildren;\n break;\n }\n\n case TREE_OPERATION_UPDATE_TREE_BASE_DURATION: {\n // id, baseDuration — skip\n i += 3;\n break;\n }\n\n case TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS: {\n // id, numErrors, numWarnings\n i += 4;\n break;\n }\n\n case TREE_OPERATION_REMOVE_ROOT: {\n const rootId = operations[i + 1];\n this.removeNode(rootId);\n i += 2;\n break;\n }\n\n case TREE_OPERATION_SET_SUBTREE_MODE: {\n // id, mode\n i += 3;\n break;\n }\n\n // ── Suspense tree operations (newer backends) ──\n\n case SUSPENSE_TREE_OPERATION_ADD: {\n // Presence of suspense ops means the backend also uses 8-field ADD\n this.extendedAddFormat = true;\n // fiberID, parentID, nameStringID, isSuspended, rects\n i += 5; // opcode + 4 fields\n i = skipRects(operations, i);\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_REMOVE: {\n this.extendedAddFormat = true;\n // numIDs, then that many IDs\n const numIds = operations[i + 1];\n i += 2 + numIds;\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_REORDER_CHILDREN: {\n this.extendedAddFormat = true;\n // parentID, numChildren, then that many child IDs\n const numSuspenseChildren = operations[i + 2];\n i += 3 + numSuspenseChildren;\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_RESIZE: {\n this.extendedAddFormat = true;\n // fiberID, rects\n i += 2; // opcode + fiberID\n i = skipRects(operations, i);\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_SUSPENDERS: {\n this.extendedAddFormat = true;\n // numChanges, then numChanges * 4 values\n const numChanges = operations[i + 1];\n i += 2 + numChanges * 4;\n break;\n }\n\n case TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE: {\n this.extendedAddFormat = true;\n // id\n i += 2;\n break;\n }\n\n default:\n // Unknown operation — skip one value and try to continue.\n // Future protocol additions may cause brief misalignment but\n // subsequent operations batches will self-correct.\n i++;\n break;\n }\n }\n\n return added;\n }\n\n private removeNode(id: number): void {\n const node = this.nodes.get(id);\n if (!node) return;\n\n // Remove from parent's children\n if (node.parentId !== null) {\n const parent = this.nodes.get(node.parentId);\n if (parent) {\n parent.children = parent.children.filter((c) => c !== id);\n }\n }\n\n // Remove from roots\n this.roots = this.roots.filter((r) => r !== id);\n\n // Remove from name index\n if (node.displayName) {\n const lower = node.displayName.toLowerCase();\n const set = this.nameIndex.get(lower);\n if (set) {\n set.delete(id);\n if (set.size === 0) this.nameIndex.delete(lower);\n }\n }\n\n // Recursively remove children\n for (const childId of node.children) {\n this.removeNode(childId);\n }\n\n this.nodes.delete(id);\n }\n\n getNode(id: number): ComponentNode | undefined {\n return this.nodes.get(id);\n }\n\n getTree(maxDepth?: number): TreeNode[] {\n const result: TreeNode[] = [];\n\n // Rebuild label maps on every getTree() call\n this.labelToId.clear();\n this.idToLabel.clear();\n let labelCounter = 1;\n\n const walk = (id: number, depth: number) => {\n const node = this.nodes.get(id);\n if (!node) return;\n if (maxDepth !== undefined && depth > maxDepth) return;\n\n const label = `@c${labelCounter++}`;\n this.labelToId.set(label, node.id);\n this.idToLabel.set(node.id, label);\n\n result.push({\n id: node.id,\n label,\n displayName: node.displayName,\n type: node.type,\n key: node.key,\n parentId: node.parentId,\n children: node.children,\n depth,\n });\n\n for (const childId of node.children) {\n walk(childId, depth + 1);\n }\n };\n\n for (const rootId of this.roots) {\n walk(rootId, 0);\n }\n return result;\n }\n\n findByName(name: string, exact?: boolean): TreeNode[] {\n const results: TreeNode[] = [];\n\n if (exact) {\n const lower = name.toLowerCase();\n const ids = this.nameIndex.get(lower);\n if (ids) {\n for (const id of ids) {\n const node = this.nodes.get(id);\n if (node && node.displayName.toLowerCase() === lower) {\n results.push(this.toTreeNode(node));\n }\n }\n }\n } else {\n const lower = name.toLowerCase();\n for (const [indexName, ids] of this.nameIndex) {\n if (indexName.includes(lower)) {\n for (const id of ids) {\n const node = this.nodes.get(id);\n if (node) {\n results.push(this.toTreeNode(node));\n }\n }\n }\n }\n }\n\n return results;\n }\n\n getComponentCount(): number {\n return this.nodes.size;\n }\n\n getCountByType(): Record<string, number> {\n const counts: Record<string, number> = {};\n for (const node of this.nodes.values()) {\n counts[node.type] = (counts[node.type] || 0) + 1;\n }\n return counts;\n }\n\n getAllNodeIds(): number[] {\n return Array.from(this.nodes.keys());\n }\n\n getRootIds(): number[] {\n return [...this.roots];\n }\n\n removeRoot(rootId: number): void {\n this.removeNode(rootId);\n }\n\n /**\n * Look up the @cN label for a given component ID.\n * Returns undefined if the ID has no label assigned.\n */\n getLabel(id: number): string | undefined {\n return this.idToLabel.get(id);\n }\n\n /**\n * Resolve a label like \"@c3\" to a real node ID.\n * Returns undefined if label not found.\n */\n resolveLabel(label: string): number | undefined {\n return this.labelToId.get(label);\n }\n\n /**\n * Resolve either a label string (\"@c3\") or a numeric ID to a real node ID.\n */\n resolveId(id: number | string): number | undefined {\n if (typeof id === 'number') return id;\n if (id.startsWith('@c')) return this.labelToId.get(id);\n // Try parsing as number\n const num = parseInt(id, 10);\n return isNaN(num) ? undefined : num;\n }\n\n private toTreeNode(node: ComponentNode): TreeNode {\n // Calculate depth by walking up the tree\n let depth = 0;\n let current = node;\n while (current.parentId !== null) {\n depth++;\n const parent = this.nodes.get(current.parentId);\n if (!parent) break;\n current = parent;\n }\n\n return {\n id: node.id,\n label: this.idToLabel.get(node.id) || `@c?`,\n displayName: node.displayName,\n type: node.type,\n key: node.key,\n parentId: node.parentId,\n children: node.children,\n depth,\n };\n }\n}\n","import type {\n ProfilingSession,\n ProfilingCommit,\n ChangeDescription,\n ComponentRenderReport,\n RenderCause,\n} from './types.js';\nimport type { ComponentTree } from './component-tree.js';\n\nexport interface ProfileSummary {\n name: string;\n duration: number;\n commitCount: number;\n componentRenderCounts: { id: number; displayName: string; label?: string; type?: string; count: number }[];\n}\n\nexport interface TimelineEntry {\n index: number;\n timestamp: number;\n duration: number;\n componentCount: number;\n}\n\nexport interface CommitDetail {\n index: number;\n timestamp: number;\n duration: number;\n components: Array<{\n id: number;\n displayName: string;\n label?: string;\n type?: string;\n actualDuration: number;\n selfDuration: number;\n causes: RenderCause[];\n }>;\n totalComponents: number;\n}\n\nexport class Profiler {\n private session: ProfilingSession | null = null;\n /** Display names captured during profiling (survives unmounts) */\n private displayNames = new Map<number, string>();\n\n isActive(): boolean {\n return this.session !== null && this.session.stoppedAt === null;\n }\n\n start(name?: string): void {\n this.displayNames.clear();\n this.session = {\n name: name || `session-${Date.now()}`,\n startedAt: Date.now(),\n stoppedAt: null,\n commits: [],\n };\n }\n\n /** Cache a component's display name (call during profiling to survive unmounts) */\n trackComponent(id: number, displayName: string): void {\n this.displayNames.set(id, displayName);\n }\n\n stop(tree?: ComponentTree): ProfileSummary | null {\n if (!this.session) return null;\n this.session.stoppedAt = Date.now();\n\n const duration = this.session.stoppedAt - this.session.startedAt;\n\n // Count renders per component\n const renderCounts = new Map<number, number>();\n for (const commit of this.session.commits) {\n for (const [id] of commit.fiberActualDurations) {\n renderCounts.set(id, (renderCounts.get(id) || 0) + 1);\n }\n }\n\n const componentRenderCounts = Array.from(renderCounts.entries())\n .map(([id, count]) => ({\n id,\n displayName: tree?.getNode(id)?.displayName || this.displayNames.get(id) || '',\n count,\n }))\n .sort((a, b) => b.count - a.count);\n\n return {\n name: this.session.name,\n duration,\n commitCount: this.session.commits.length,\n componentRenderCounts,\n };\n }\n\n /**\n * Process profiling data sent from React DevTools.\n *\n * The data format varies between React versions. We handle the common\n * format where each commit contains:\n * - commitTime\n * - duration\n * - fiberActualDurations: [id, duration, ...]\n * - fiberSelfDurations: [id, duration, ...]\n * - changeDescriptions: Map<id, description>\n */\n processProfilingData(payload: unknown): void {\n if (!this.session || this.session.stoppedAt !== null) return;\n\n const data = payload as {\n dataForRoots?: Array<{\n commitData?: Array<{\n changeDescriptions?: Array<[number, unknown]> | Map<number, unknown>;\n duration?: number;\n fiberActualDurations?: Array<[number, number]> | number[];\n fiberSelfDurations?: Array<[number, number]> | number[];\n timestamp?: number;\n }>;\n operations?: unknown[];\n }>;\n // Alternative flat format\n commitData?: Array<{\n changeDescriptions?: Array<[number, unknown]> | Map<number, unknown>;\n duration?: number;\n fiberActualDurations?: Array<[number, number]> | number[];\n fiberSelfDurations?: Array<[number, number]> | number[];\n timestamp?: number;\n }>;\n };\n\n // Handle nested format (dataForRoots)\n const roots = data?.dataForRoots;\n if (roots) {\n for (const root of roots) {\n if (root.commitData) {\n for (const commitData of root.commitData) {\n this.processCommitData(commitData);\n }\n }\n }\n return;\n }\n\n // Handle flat format\n if (data?.commitData) {\n for (const commitData of data.commitData) {\n this.processCommitData(commitData);\n }\n }\n }\n\n private processCommitData(commitData: {\n changeDescriptions?: Array<[number, unknown]> | Map<number, unknown>;\n duration?: number;\n fiberActualDurations?: Array<[number, number]> | number[];\n fiberSelfDurations?: Array<[number, number]> | number[];\n timestamp?: number;\n }): void {\n const commit: ProfilingCommit = {\n timestamp: commitData.timestamp || Date.now(),\n duration: commitData.duration || 0,\n fiberActualDurations: new Map(),\n fiberSelfDurations: new Map(),\n changeDescriptions: new Map(),\n };\n\n // Parse fiber durations (can be [id, duration, id, duration, ...] or [[id, duration], ...])\n if (commitData.fiberActualDurations) {\n parseDurations(commitData.fiberActualDurations, commit.fiberActualDurations);\n }\n if (commitData.fiberSelfDurations) {\n parseDurations(commitData.fiberSelfDurations, commit.fiberSelfDurations);\n }\n\n // Parse change descriptions\n if (commitData.changeDescriptions) {\n const entries =\n commitData.changeDescriptions instanceof Map\n ? commitData.changeDescriptions.entries()\n : commitData.changeDescriptions[Symbol.iterator]();\n for (const [id, desc] of entries) {\n const d = desc as {\n didHooksChange?: boolean;\n isFirstMount?: boolean;\n props?: string[] | null;\n state?: string[] | null;\n hooks?: number[] | null;\n };\n commit.changeDescriptions.set(id as number, {\n didHooksChange: d.didHooksChange || false,\n isFirstMount: d.isFirstMount || false,\n props: d.props || null,\n state: d.state || null,\n hooks: d.hooks || null,\n });\n }\n }\n\n this.session!.commits.push(commit);\n }\n\n getReport(\n componentId: number,\n tree: ComponentTree,\n ): ComponentRenderReport | null {\n if (!this.session) return null;\n\n const node = tree.getNode(componentId);\n let renderCount = 0;\n let totalDuration = 0;\n let maxDuration = 0;\n const causeSet = new Set<RenderCause>();\n\n for (const commit of this.session.commits) {\n const duration = commit.fiberActualDurations.get(componentId);\n if (duration !== undefined) {\n renderCount++;\n totalDuration += duration;\n if (duration > maxDuration) maxDuration = duration;\n\n const desc = commit.changeDescriptions.get(componentId);\n if (desc) {\n for (const cause of describeCauses(desc)) {\n causeSet.add(cause);\n }\n }\n }\n }\n\n if (renderCount === 0) return null;\n\n return {\n id: componentId,\n displayName: node?.displayName || this.displayNames.get(componentId) || `Component#${componentId}`,\n renderCount,\n totalDuration,\n avgDuration: totalDuration / renderCount,\n maxDuration,\n causes: Array.from(causeSet),\n };\n }\n\n getSlowest(\n tree: ComponentTree,\n limit = 10,\n ): ComponentRenderReport[] {\n return this.getAllReports(tree)\n .sort((a, b) => b.avgDuration - a.avgDuration)\n .slice(0, limit);\n }\n\n getMostRerenders(\n tree: ComponentTree,\n limit = 10,\n ): ComponentRenderReport[] {\n return this.getAllReports(tree)\n .sort((a, b) => b.renderCount - a.renderCount)\n .slice(0, limit);\n }\n\n getCommitDetails(index: number, tree: ComponentTree, limit = 10): CommitDetail | null {\n if (!this.session) return null;\n if (index < 0 || index >= this.session.commits.length) return null;\n\n const commit = this.session.commits[index];\n const components: CommitDetail['components'] = [];\n\n for (const [id, actualDuration] of commit.fiberActualDurations) {\n const selfDuration = commit.fiberSelfDurations.get(id) || 0;\n const desc = commit.changeDescriptions.get(id);\n components.push({\n id,\n displayName: tree.getNode(id)?.displayName || this.displayNames.get(id) || `Component#${id}`,\n actualDuration,\n selfDuration,\n causes: desc ? describeCauses(desc) : [],\n });\n }\n\n components.sort((a, b) => b.selfDuration - a.selfDuration);\n\n const totalCount = components.length;\n\n return {\n index,\n timestamp: commit.timestamp,\n duration: commit.duration,\n components: limit > 0 ? components.slice(0, limit) : components,\n totalComponents: totalCount,\n };\n }\n\n getTimeline(limit?: number): TimelineEntry[] {\n if (!this.session) return [];\n\n const entries = this.session.commits.map((commit, index) => ({\n index,\n timestamp: commit.timestamp,\n duration: commit.duration,\n componentCount: commit.fiberActualDurations.size,\n }));\n\n if (limit) return entries.slice(0, limit);\n return entries;\n }\n\n private getAllReports(tree: ComponentTree): ComponentRenderReport[] {\n if (!this.session) return [];\n\n // Collect all component IDs that appear in profiling data\n const componentIds = new Set<number>();\n for (const commit of this.session.commits) {\n for (const id of commit.fiberActualDurations.keys()) {\n componentIds.add(id);\n }\n }\n\n const reports: ComponentRenderReport[] = [];\n for (const id of componentIds) {\n const report = this.getReport(id, tree);\n if (report) reports.push(report);\n }\n return reports;\n }\n}\n\nfunction parseDurations(\n raw: Array<[number, number]> | number[],\n target: Map<number, number>,\n): void {\n if (raw.length === 0) return;\n\n // Check if it's array of tuples or flat array\n if (Array.isArray(raw[0])) {\n // [[id, duration], ...]\n for (const [id, duration] of raw as Array<[number, number]>) {\n target.set(id, duration);\n }\n } else {\n // [id, duration, id, duration, ...]\n const flat = raw as number[];\n for (let i = 0; i < flat.length; i += 2) {\n target.set(flat[i], flat[i + 1]);\n }\n }\n}\n\nfunction describeCauses(desc: ChangeDescription): RenderCause[] {\n const causes: RenderCause[] = [];\n if (desc.isFirstMount) {\n causes.push('first-mount');\n return causes;\n }\n if (desc.props && desc.props.length > 0) causes.push('props-changed');\n if (desc.state && desc.state.length > 0) causes.push('state-changed');\n if (desc.didHooksChange) causes.push('hooks-changed');\n // If no specific cause found, it was likely parent-triggered\n if (causes.length === 0) causes.push('parent-rendered');\n return causes;\n}\n"],"mappings":"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","names":["port","pending","port"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-react-devtools",
3
- "version": "0.2.2",
3
+ "version": "0.3.0-canary-20260212081524",
4
4
  "description": "CLI tool for AI agents to inspect React component trees and profile performance",
5
5
  "type": "module",
6
6
  "bin": {
@@ -56,12 +56,12 @@ agent-react-devtools profile commit 3 # Detail for commit #3
56
56
  Every component gets a stable label like `@c1`, `@c2`. Use these to reference components in follow-up commands:
57
57
 
58
58
  ```
59
- @c1 [fn] "App"
60
- ├─ @c2 [fn] "Header"
61
- ├─ @c3 [fn] "TodoList"
62
- │ ├─ @c4 [fn] "TodoItem" key="1"
63
- │ └─ @c5 [fn] "TodoItem" key="2"
64
- └─ @c6 [host] "div"
59
+ @c1 [fn] App
60
+ ├─ @c2 [fn] Header
61
+ ├─ @c3 [fn] TodoList
62
+ │ ├─ @c4 [fn] TodoItem key=1
63
+ │ └─ @c5 [fn] TodoItem key=2
64
+ └─ @c6 [host] div
65
65
  ```
66
66
 
67
67
  Type abbreviations: `fn` = function, `cls` = class, `host` = DOM element, `memo` = React.memo, `fRef` = forwardRef, `susp` = Suspense, `ctx` = context.
@@ -69,7 +69,7 @@ Type abbreviations: `fn` = function, `cls` = class, `host` = DOM element, `memo`
69
69
  ### Inspected Component
70
70
 
71
71
  ```
72
- @c3 [fn] "TodoList"
72
+ @c3 [fn] TodoList
73
73
  props:
74
74
  items: [{"id":1,"text":"Buy milk"},{"id":2,"text":"Walk dog"}]
75
75
  onDelete: ƒ
@@ -87,8 +87,8 @@ hooks:
87
87
 
88
88
  ```
89
89
  Slowest (by avg render time):
90
- ExpensiveList avg:12.3ms max:18.1ms renders:47 cause:props-changed
91
- TodoItem avg:2.1ms max:5.0ms renders:94 cause:parent-rendered
90
+ @c3 [fn] ExpensiveList avg:12.3ms max:18.1ms renders:47 causes:props-changed
91
+ @c4 [fn] TodoItem avg:2.1ms max:5.0ms renders:94 causes:parent-rendered, props-changed
92
92
  ```
93
93
 
94
94
  Render causes: `props-changed`, `state-changed`, `hooks-changed`, `parent-rendered`, `force-update`, `first-mount`.
@@ -58,12 +58,12 @@ Stop profiling and collect data from React. Shows a summary with duration, commi
58
58
  ### `agent-react-devtools profile slow [--limit N]`
59
59
  Rank components by average render duration (slowest first). Default limit: 10.
60
60
 
61
- Output columns: component name, avg duration, max duration, render count, primary cause.
61
+ Output columns: label, type tag, component name, avg duration, max duration, render count, all causes.
62
62
 
63
63
  ### `agent-react-devtools profile rerenders [--limit N]`
64
64
  Rank components by render count (most re-renders first). Default limit: 10.
65
65
 
66
- Output columns: component name, render count, primary cause.
66
+ Output columns: label, type tag, component name, render count, all causes.
67
67
 
68
68
  ### `agent-react-devtools profile report <@cN | id>`
69
69
  Detailed render report for a single component: render count, avg/max/total duration, all render causes.