tui-devtools 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/daemon.ts","../src/server.ts","../src/store.ts","../src/types.ts","../src/bridge.ts","../src/pty-session.ts","../src/session-manager.ts"],"sourcesContent":["/**\n * daemon.ts — Background daemon with IPC server\n *\n * Manages the DevTools WebSocket server as a long-running process.\n * CLI commands communicate with the daemon via Unix socket IPC.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport net from 'node:net';\nimport { DevToolsServer } from './server.js';\nimport { SessionManager } from './session-manager.js';\nimport type { IpcRequest, IpcResponse, LogEntry } from './types.js';\n\nconst BASE_DIR = path.join(process.env.HOME ?? '/tmp', '.tui-devtools');\n\nfunction ensureBaseDir(): void {\n fs.mkdirSync(BASE_DIR, { recursive: true });\n}\n\nexport function getSocketPath(session: string): string {\n return path.join(BASE_DIR, `${session}.sock`);\n}\n\nexport function getPidPath(session: string): string {\n return path.join(BASE_DIR, `${session}.pid`);\n}\n\nexport function getLogPath(session: string): string {\n return path.join(BASE_DIR, `${session}.log`);\n}\n\n/** Check if daemon is already running for a session */\nexport function isDaemonRunning(session: string): boolean {\n const pidPath = getPidPath(session);\n try {\n const pid = parseInt(fs.readFileSync(pidPath, 'utf-8').trim(), 10);\n process.kill(pid, 0); // Check if process exists\n return true;\n } catch {\n return false;\n }\n}\n\n/** Send IPC request to running daemon */\nexport function sendIpcRequest(session: string, request: IpcRequest): Promise<IpcResponse> {\n return new Promise((resolve, reject) => {\n const socketPath = getSocketPath(session);\n const client = net.createConnection(socketPath);\n let buffer = '';\n\n client.on('connect', () => {\n client.write(JSON.stringify(request) + '\\n');\n });\n\n client.on('data', (data) => {\n buffer += data.toString();\n const lines = buffer.split('\\n');\n if (lines.length > 1) {\n try {\n const response = JSON.parse(lines[0]!) as IpcResponse;\n client.end();\n resolve(response);\n } catch (e) {\n reject(new Error(`Invalid IPC response: ${lines[0]}`));\n }\n }\n });\n\n client.on('error', (err) => {\n reject(new Error(`Cannot connect to daemon (session: ${session}): ${err.message}`));\n });\n\n setTimeout(() => {\n client.destroy();\n reject(new Error('IPC timeout'));\n }, 10000);\n });\n}\n\n/** Start the daemon process (runs in foreground — caller should fork) */\nexport async function startDaemon(session: string, port: number): Promise<void> {\n ensureBaseDir();\n\n // Clean up stale socket\n const socketPath = getSocketPath(session);\n try { fs.unlinkSync(socketPath); } catch {}\n\n // Write PID\n fs.writeFileSync(getPidPath(session), String(process.pid));\n\n // Log file\n const logStream = fs.createWriteStream(getLogPath(session), { flags: 'a' });\n const log = (msg: string) => {\n const ts = new Date().toISOString();\n logStream.write(`[${ts}] ${msg}\\n`);\n };\n\n // Session manager for PTY sessions\n const sessionMgr = new SessionManager();\n\n // Start DevTools server\n const devtools = new DevToolsServer({\n port,\n onLog: (entry: LogEntry) => {\n log(`[${entry.level}] ${entry.args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ')}`);\n },\n onConnect: () => log('App connected'),\n onDisconnect: () => log('App disconnected'),\n debugLog: (msg: string) => log(msg),\n });\n\n await devtools.start();\n log(`DevTools server listening on port ${port}`);\n\n // Start IPC server\n const ipcServer = net.createServer((conn) => {\n let buffer = '';\n conn.on('data', async (data) => {\n buffer += data.toString();\n const lines = buffer.split('\\n');\n if (lines.length <= 1) return;\n buffer = lines.slice(1).join('\\n');\n\n try {\n const req = JSON.parse(lines[0]!) as IpcRequest;\n const res = await handleIpcRequest(req, devtools, sessionMgr, log);\n conn.write(JSON.stringify(res) + '\\n');\n } catch (e) {\n conn.write(JSON.stringify({ ok: false, error: String(e) }) + '\\n');\n }\n });\n });\n\n ipcServer.listen(socketPath);\n log(`IPC server listening on ${socketPath}`);\n\n // Graceful shutdown\n const cleanup = () => {\n log('Shutting down...');\n sessionMgr.killAll();\n devtools.stop();\n ipcServer.close();\n try { fs.unlinkSync(socketPath); } catch {}\n try { fs.unlinkSync(getPidPath(session)); } catch {}\n logStream.end();\n process.exit(0);\n };\n\n process.on('SIGTERM', cleanup);\n process.on('SIGINT', cleanup);\n}\n\nasync function handleIpcRequest(\n req: IpcRequest,\n devtools: DevToolsServer,\n sessionMgr: SessionManager,\n log: (msg: string) => void,\n): Promise<IpcResponse> {\n const store = devtools.getStore();\n const bridge = devtools.getBridge();\n\n switch (req.command) {\n // ─── DevTools commands ───\n case 'status':\n return {\n ok: true,\n data: {\n connected: store.connected,\n appName: store.appName,\n nodeCount: store.nodes.size,\n rootCount: store.roots.size,\n logCount: store.logs.length,\n rendererIds: store.rendererIds,\n sessions: sessionMgr.list(),\n },\n };\n\n case 'tree': {\n const depth = (req.args?.depth as number) ?? 20;\n const json = req.args?.json as boolean;\n if (json) {\n return { ok: true, data: store.getTreeJson(undefined, depth) };\n }\n return { ok: true, data: store.getTree(undefined, depth) };\n }\n\n case 'inspect': {\n const name = req.args?.name as string | undefined;\n const id = req.args?.id as number | undefined;\n\n let node = id != null ? store.nodes.get(id) : null;\n if (!node && name) {\n node = store.findByName(name);\n }\n\n if (!node) {\n return { ok: false, error: `Component not found: ${name ?? id}` };\n }\n\n const inspectData = await bridge.inspectElement(node.id);\n\n return {\n ok: true,\n data: {\n id: node.id,\n displayName: node.displayName,\n type: node.type,\n key: node.key,\n parentId: node.parentId,\n childIds: node.childIds,\n props: node.props,\n state: node.state,\n inspectData,\n },\n };\n }\n\n case 'logs': {\n const level = req.args?.level as string | undefined;\n const tail = (req.args?.tail as number) ?? 50;\n\n let logs = store.logs;\n if (level) {\n logs = logs.filter(l => l.level === level);\n }\n logs = logs.slice(-tail);\n\n return { ok: true, data: logs };\n }\n\n case 'find': {\n const name = req.args?.name as string;\n if (!name) return { ok: false, error: 'name is required' };\n const nodes = store.findAllByName(name);\n return {\n ok: true,\n data: nodes.map(n => ({\n id: n.id,\n displayName: n.displayName,\n type: n.type,\n key: n.key,\n })),\n };\n }\n\n // ─── PTY automation commands ───\n case 'run': {\n const command = req.args?.command as string;\n const sessionId = req.args?.sessionId as string ?? 'default';\n const cwd = req.args?.cwd as string | undefined;\n const cols = req.args?.cols as number | undefined;\n const rows = req.args?.rows as number | undefined;\n const env = req.args?.env as Record<string, string> | undefined;\n\n if (!command) return { ok: false, error: 'command is required' };\n\n log(`[PTY] run session=${sessionId} command=${command}`);\n const info = sessionMgr.create(sessionId, { command, cwd, cols, rows, env });\n return { ok: true, data: info };\n }\n\n case 'screenshot': {\n const sessionId = req.args?.sessionId as string ?? 'default';\n const stripAnsi = req.args?.stripAnsi as boolean;\n const session = sessionMgr.get(sessionId);\n if (!session) return { ok: false, error: `Session not found: ${sessionId}` };\n\n const text = session.screenshot({ stripAnsi });\n return { ok: true, data: { screenshot: text, running: session.running } };\n }\n\n case 'press': {\n const sessionId = req.args?.sessionId as string ?? 'default';\n const keys = req.args?.keys as string[];\n const session = sessionMgr.get(sessionId);\n if (!session) return { ok: false, error: `Session not found: ${sessionId}` };\n\n for (const key of (keys ?? [])) {\n session.press(key);\n }\n return { ok: true };\n }\n\n case 'type': {\n const sessionId = req.args?.sessionId as string ?? 'default';\n const text = req.args?.text as string;\n const session = sessionMgr.get(sessionId);\n if (!session) return { ok: false, error: `Session not found: ${sessionId}` };\n if (!text) return { ok: false, error: 'text is required' };\n\n session.type(text);\n return { ok: true };\n }\n\n case 'scroll': {\n const sessionId = req.args?.sessionId as string ?? 'default';\n const direction = (req.args?.direction as string) ?? 'down';\n const amount = (req.args?.amount as number) ?? 1;\n const session = sessionMgr.get(sessionId);\n if (!session) return { ok: false, error: `Session not found: ${sessionId}` };\n\n session.scroll(direction as 'up' | 'down', amount);\n return { ok: true };\n }\n\n case 'wait': {\n const sessionId = req.args?.sessionId as string ?? 'default';\n const text = req.args?.text as string;\n const timeout = (req.args?.timeout as number) ?? 30000;\n const session = sessionMgr.get(sessionId);\n if (!session) return { ok: false, error: `Session not found: ${sessionId}` };\n if (!text) return { ok: false, error: 'text is required' };\n\n const found = await session.wait(text, timeout);\n return { ok: true, data: { found, screenshot: session.screenshot() } };\n }\n\n case 'resize': {\n const sessionId = req.args?.sessionId as string ?? 'default';\n const cols = req.args?.cols as number ?? 120;\n const rows = req.args?.rows as number ?? 40;\n const session = sessionMgr.get(sessionId);\n if (!session) return { ok: false, error: `Session not found: ${sessionId}` };\n\n session.resize(cols, rows);\n return { ok: true };\n }\n\n case 'kill-session': {\n const sessionId = req.args?.sessionId as string ?? 'default';\n const killed = sessionMgr.kill(sessionId);\n return { ok: killed, error: killed ? undefined : `Session not found: ${sessionId}` };\n }\n\n case 'sessions':\n return { ok: true, data: sessionMgr.list() };\n\n default:\n return { ok: false, error: `Unknown command: ${req.command}` };\n }\n}\n","/**\n * server.ts — WebSocket server for React DevTools connections\n *\n * Listens on a port (default 8097) and waits for Ink apps to connect.\n * When DEV=true, Ink's reconciler calls connectToDevTools() which\n * connects to this server as a WebSocket client.\n */\n\nimport { WebSocketServer, type WebSocket } from 'ws';\nimport { DevToolsStore } from './store.js';\nimport { DevToolsBridge } from './bridge.js';\nimport type { LogEntry } from './types.js';\n\nexport interface ServerOptions {\n port: number;\n host?: string;\n onLog?: (entry: LogEntry) => void;\n onConnect?: () => void;\n onDisconnect?: () => void;\n debugLog?: (msg: string) => void;\n}\n\nexport class DevToolsServer {\n private wss: WebSocketServer | null = null;\n private store: DevToolsStore;\n private bridge: DevToolsBridge;\n private options: ServerOptions;\n\n constructor(options: ServerOptions) {\n this.options = options;\n this.store = new DevToolsStore();\n this.bridge = new DevToolsBridge(this.store, options.onLog, options.debugLog);\n }\n\n start(): Promise<void> {\n return new Promise((resolve, reject) => {\n const host = this.options.host ?? '127.0.0.1';\n this.wss = new WebSocketServer({ port: this.options.port, host });\n\n this.wss.on('listening', () => {\n resolve();\n });\n\n this.wss.on('error', (err) => {\n reject(err);\n });\n\n this.wss.on('connection', (ws: WebSocket) => {\n this.bridge.attach(ws);\n this.options.onConnect?.();\n\n ws.on('close', () => {\n this.options.onDisconnect?.();\n });\n });\n });\n }\n\n stop(): void {\n this.bridge.detach();\n this.wss?.close();\n this.wss = null;\n }\n\n getStore(): DevToolsStore {\n return this.store;\n }\n\n getBridge(): DevToolsBridge {\n return this.bridge;\n }\n\n isConnected(): boolean {\n return this.store.connected;\n }\n}\n","import type { FiberNode, LogEntry } from './types.js';\n\nconst MAX_LOGS = 500;\n\nexport class DevToolsStore {\n roots = new Map<number, FiberNode>();\n nodes = new Map<number, FiberNode>();\n logs: LogEntry[] = [];\n connected = false;\n appName: string | null = null;\n rendererIds: number[] = [];\n\n // Pending inspection responses keyed by request ID\n private inspectCallbacks = new Map<number, (data: unknown) => void>();\n private nextRequestId = 1;\n\n addNode(node: FiberNode): void {\n this.nodes.set(node.id, node);\n if (node.parentId === null || node.parentId === 0) {\n this.roots.set(node.id, node);\n }\n }\n\n removeNode(id: number): void {\n const node = this.nodes.get(id);\n if (node) {\n // Remove from parent's children\n if (node.parentId !== null) {\n const parent = this.nodes.get(node.parentId);\n if (parent) {\n parent.childIds = parent.childIds.filter(cid => cid !== id);\n }\n }\n // Remove children recursively\n for (const childId of node.childIds) {\n this.removeNode(childId);\n }\n this.nodes.delete(id);\n this.roots.delete(id);\n }\n }\n\n addLog(entry: LogEntry): void {\n this.logs.push(entry);\n if (this.logs.length > MAX_LOGS) {\n this.logs = this.logs.slice(-MAX_LOGS);\n }\n }\n\n findByName(name: string): FiberNode | null {\n for (const node of this.nodes.values()) {\n if (node.displayName === name) return node;\n }\n // Partial match\n for (const node of this.nodes.values()) {\n if (node.displayName?.includes(name)) return node;\n }\n return null;\n }\n\n findAllByName(name: string): FiberNode[] {\n const results: FiberNode[] = [];\n for (const node of this.nodes.values()) {\n if (node.displayName?.includes(name)) results.push(node);\n }\n return results;\n }\n\n getTree(rootId?: number, maxDepth = 20): string {\n const lines: string[] = [];\n const roots = rootId ? [this.nodes.get(rootId)].filter(Boolean) as FiberNode[] : [...this.roots.values()];\n\n for (const root of roots) {\n this.printNode(root, 0, maxDepth, lines);\n }\n return lines.join('\\n');\n }\n\n getTreeJson(rootId?: number, maxDepth = 20): object[] {\n const roots = rootId ? [this.nodes.get(rootId)].filter(Boolean) as FiberNode[] : [...this.roots.values()];\n return roots.map(r => this.nodeToJson(r, 0, maxDepth));\n }\n\n private printNode(node: FiberNode, depth: number, maxDepth: number, lines: string[]): void {\n if (depth > maxDepth) return;\n const indent = ' '.repeat(depth);\n const name = node.displayName || `<${node.type}>`;\n const keyStr = node.key ? ` key=\"${node.key}\"` : '';\n lines.push(`${indent}${name}${keyStr} [${node.id}]`);\n for (const childId of node.childIds) {\n const child = this.nodes.get(childId);\n if (child) this.printNode(child, depth + 1, maxDepth, lines);\n }\n }\n\n private nodeToJson(node: FiberNode, depth: number, maxDepth: number): object {\n const children = depth < maxDepth\n ? node.childIds\n .map(id => this.nodes.get(id))\n .filter(Boolean)\n .map(child => this.nodeToJson(child!, depth + 1, maxDepth))\n : [];\n return {\n id: node.id,\n name: node.displayName,\n type: node.type,\n key: node.key,\n children,\n };\n }\n\n registerInspectCallback(callback: (data: unknown) => void): number {\n const id = this.nextRequestId++;\n this.inspectCallbacks.set(id, callback);\n return id;\n }\n\n resolveInspectCallback(requestId: number, data: unknown): void {\n const cb = this.inspectCallbacks.get(requestId);\n if (cb) {\n this.inspectCallbacks.delete(requestId);\n cb(data);\n }\n }\n\n clear(): void {\n this.roots.clear();\n this.nodes.clear();\n this.logs = [];\n this.connected = false;\n this.appName = null;\n this.rendererIds = [];\n }\n}\n","export interface FiberNode {\n id: number;\n displayName: string | null;\n type: 'function' | 'class' | 'host' | 'other';\n parentId: number | null;\n childIds: number[];\n key: string | null;\n // Populated on-demand via inspectElement\n props?: Record<string, unknown>;\n state?: Record<string, unknown>;\n hooks?: HookInfo[];\n}\n\nexport interface HookInfo {\n id: number | null;\n name: string;\n value: unknown;\n subHooks?: HookInfo[];\n}\n\nexport interface LogEntry {\n level: 'log' | 'warn' | 'error' | 'info' | 'debug';\n args: unknown[];\n timestamp: number;\n componentStack?: string;\n}\n\nexport interface IpcRequest {\n command: string;\n args?: Record<string, unknown>;\n}\n\nexport interface IpcResponse {\n ok: boolean;\n data?: unknown;\n error?: string;\n}\n\n// React DevTools protocol constants\n// See: https://github.com/facebook/react/blob/main/packages/react-devtools-shared/src/constants.js\nexport const TREE_OPERATION_ADD = 1;\nexport const TREE_OPERATION_REMOVE = 2;\nexport const TREE_OPERATION_REORDER_CHILDREN = 3;\nexport const TREE_OPERATION_UPDATE_TREE_BASE_DURATION = 4;\nexport const TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS = 5;\nexport const TREE_OPERATION_REMOVE_ROOT = 6;\nexport const TREE_OPERATION_SET_SUBTREE_MODE = 7;\n\nexport const ElementTypeClass = 1;\nexport const ElementTypeFunction = 2;\nexport const ElementTypeContext = 3;\nexport const ElementTypeForwardRef = 4;\nexport const ElementTypeHostComponent = 5;\nexport const ElementTypeMemo = 6;\nexport const ElementTypeOtherOrUnknown = 7;\nexport const ElementTypeProfiler = 8;\nexport const ElementTypeRoot = 9;\nexport const ElementTypeSuspense = 10;\nexport const ElementTypeSuspenseList = 11;\nexport const ElementTypeTracingMarker = 12;\n","/**\n * bridge.ts — Parses React DevTools protocol messages\n *\n * The DevTools protocol uses a simple JSON-based message format over WebSocket:\n * { event: string, payload: unknown }\n *\n * Key events:\n * - \"operations\": Fiber tree mutations (add/remove/reorder nodes)\n * - \"inspectedElement\": Response to element inspection requests\n * - \"shutdown\": App disconnecting\n *\n * Operations payload is an Int32Array with a compact binary format.\n * See: react-devtools-shared/src/devtools/store.js\n */\n\nimport type { WebSocket } from 'ws';\nimport { DevToolsStore } from './store.js';\nimport type { FiberNode, LogEntry } from './types.js';\nimport {\n TREE_OPERATION_ADD,\n TREE_OPERATION_REMOVE,\n TREE_OPERATION_REORDER_CHILDREN,\n TREE_OPERATION_UPDATE_TREE_BASE_DURATION,\n TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS,\n TREE_OPERATION_REMOVE_ROOT,\n TREE_OPERATION_SET_SUBTREE_MODE,\n ElementTypeClass,\n ElementTypeFunction,\n ElementTypeHostComponent,\n ElementTypeRoot,\n} from './types.js';\n\nexport class DevToolsBridge {\n private ws: WebSocket | null = null;\n private store: DevToolsStore;\n private onLog?: (entry: LogEntry) => void;\n\n private debugLog?: (msg: string) => void;\n\n constructor(store: DevToolsStore, onLog?: (entry: LogEntry) => void, debugLog?: (msg: string) => void) {\n this.store = store;\n this.onLog = onLog;\n this.debugLog = debugLog;\n }\n\n attach(ws: WebSocket): void {\n this.ws = ws;\n this.store.connected = true;\n\n ws.on('message', (data: Buffer | string) => {\n try {\n const raw = typeof data === 'string' ? data : data.toString();\n const msg = JSON.parse(raw);\n this.debugLog?.(`[MSG] event=${msg.event} payload_type=${typeof msg.payload} payload_keys=${msg.payload && typeof msg.payload === 'object' ? Object.keys(msg.payload).join(',') : Array.isArray(msg.payload) ? `array[${msg.payload.length}]` : String(msg.payload)?.slice(0, 80)}`);\n this.handleMessage(msg);\n } catch (e) {\n this.debugLog?.(`[PARSE_ERR] ${(e as Error).message} raw=${(typeof data === 'string' ? data : data.toString()).slice(0, 200)}`);\n }\n });\n\n ws.on('close', () => {\n this.store.connected = false;\n this.ws = null;\n });\n }\n\n private handleMessage(msg: { event: string; payload?: unknown }): void {\n switch (msg.event) {\n case 'operations': {\n // Payload may be a plain object with numeric keys (serialized from Int32Array)\n let ops: number[];\n if (Array.isArray(msg.payload)) {\n ops = msg.payload;\n } else if (msg.payload && typeof msg.payload === 'object') {\n const obj = msg.payload as Record<string, number>;\n const keys = Object.keys(obj).map(Number).sort((a, b) => a - b);\n ops = keys.map(k => obj[String(k)]!);\n } else {\n break;\n }\n this.debugLog?.(`[OPS] parsed ${ops.length} entries: [${ops.join(',')}]`);\n this.handleOperations(ops);\n break;\n }\n\n case 'inspectedElement':\n this.handleInspectedElement(msg.payload);\n break;\n\n case 'shutdown':\n this.store.connected = false;\n break;\n\n // Console capture — DevTools patches console methods and sends logs\n case 'console-log':\n case 'console-warn':\n case 'console-error':\n case 'console-info':\n case 'console-debug': {\n const level = msg.event.replace('console-', '') as LogEntry['level'];\n const entry: LogEntry = {\n level,\n args: Array.isArray(msg.payload) ? msg.payload : [msg.payload],\n timestamp: Date.now(),\n };\n this.store.addLog(entry);\n this.onLog?.(entry);\n break;\n }\n\n // DevTools backend sends renderer info\n case 'renderer': {\n const payload = msg.payload as { id: number; rendererPackageName?: string } | undefined;\n if (payload?.id != null) {\n this.store.rendererIds.push(payload.id);\n }\n break;\n }\n\n case 'renderer-attached': {\n const payload = msg.payload as { id: number } | undefined;\n if (payload?.id != null && !this.store.rendererIds.includes(payload.id)) {\n this.store.rendererIds.push(payload.id);\n }\n break;\n }\n }\n }\n\n private handleOperations(ops: number[]): void {\n if (!ops || ops.length === 0) return;\n\n // Operations format:\n // [rendererID, rootFiberID, stringTableSize, ...stringTable, ...operations]\n //\n // String table entries: [charCount, ...charCodes]\n // Operations use string table INDICES (not inline char codes)\n // ADD: [op, id, elementType, parentId, ownerID, displayNameIndex, keyIndex]\n\n let i = 0;\n const rendererId = ops[i++]!;\n const rootId = ops[i++]!;\n\n // Ensure renderer is tracked\n if (!this.store.rendererIds.includes(rendererId)) {\n this.store.rendererIds.push(rendererId);\n }\n\n // Parse string table\n const stringTableSize = ops[i++]!;\n const stringTable: string[] = ['']; // index 0 = empty string\n const stringTableEnd = i + stringTableSize;\n while (i < stringTableEnd) {\n const len = ops[i++]!;\n const chars: string[] = [];\n for (let j = 0; j < len; j++) {\n chars.push(String.fromCharCode(ops[i++]!));\n }\n stringTable.push(chars.join(''));\n }\n\n this.debugLog?.(`[OPS] stringTable=[${stringTable.join(',')}] remaining=${ops.length - i} ops`);\n\n while (i < ops.length) {\n const op = ops[i++]!;\n\n switch (op) {\n case TREE_OPERATION_ADD: {\n const id = ops[i++]!;\n const elementType = ops[i++]!;\n const parentId = ops[i++]!;\n const ownerID = ops[i++]!;\n void ownerID;\n const displayNameIndex = ops[i++]!;\n const keyIndex = ops[i++]!;\n\n const displayName = stringTable[displayNameIndex] || null;\n const key = stringTable[keyIndex] || null;\n\n let type: FiberNode['type'] = 'other';\n if (elementType === ElementTypeFunction) type = 'function';\n else if (elementType === ElementTypeClass) type = 'class';\n else if (elementType === ElementTypeHostComponent) type = 'host';\n else if (elementType === ElementTypeRoot) type = 'other';\n\n const resolvedParentId = parentId === 0 ? null : parentId;\n\n const node: FiberNode = {\n id,\n displayName,\n type,\n parentId: resolvedParentId,\n childIds: [],\n key,\n };\n\n this.debugLog?.(`[ADD] id=${id} type=${type} parent=${resolvedParentId} name=${displayName}`);\n this.store.addNode(node);\n\n // Add to parent's children\n if (resolvedParentId != null) {\n const parent = this.store.nodes.get(resolvedParentId);\n if (parent && !parent.childIds.includes(id)) {\n parent.childIds.push(id);\n }\n }\n break;\n }\n\n case TREE_OPERATION_REMOVE: {\n const removeCount = ops[i++]!;\n for (let j = 0; j < removeCount; j++) {\n const id = ops[i++]!;\n this.store.removeNode(id);\n }\n break;\n }\n\n case TREE_OPERATION_REORDER_CHILDREN: {\n const id = ops[i++]!;\n const childCount = ops[i++]!;\n const newChildIds: number[] = [];\n for (let j = 0; j < childCount; j++) {\n newChildIds.push(ops[i++]!);\n }\n const node = this.store.nodes.get(id);\n if (node) node.childIds = newChildIds;\n break;\n }\n\n case TREE_OPERATION_UPDATE_TREE_BASE_DURATION: {\n i++; // id\n i++; // duration\n break;\n }\n\n case TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS: {\n i++; // id\n i++; // errors count\n i++; // warnings count\n break;\n }\n\n case TREE_OPERATION_REMOVE_ROOT: {\n break;\n }\n\n case TREE_OPERATION_SET_SUBTREE_MODE: {\n i++; // id\n i++; // mode\n break;\n }\n\n default:\n this.debugLog?.(`[OPS] unknown op=${op} at index=${i - 1}`);\n break;\n }\n }\n }\n\n private handleInspectedElement(payload: unknown): void {\n const p = payload as {\n id?: number;\n responseID?: number;\n type?: string;\n value?: {\n props?: Record<string, unknown>;\n state?: Record<string, unknown>;\n hooks?: unknown[];\n };\n };\n\n if (p?.responseID != null) {\n this.store.resolveInspectCallback(p.responseID, p.value);\n }\n\n // Also update node's cached data\n if (p?.id != null && p?.value) {\n const node = this.store.nodes.get(p.id);\n if (node) {\n if (p.value.props) node.props = p.value.props;\n if (p.value.state) node.state = p.value.state;\n }\n }\n }\n\n /** Request element inspection from the DevTools backend */\n inspectElement(id: number): Promise<unknown> {\n return new Promise((resolve, reject) => {\n if (!this.ws) {\n reject(new Error('Not connected'));\n return;\n }\n\n const requestId = this.store.registerInspectCallback(resolve);\n const rendererId = this.store.rendererIds[0] ?? 1;\n\n this.ws.send(JSON.stringify({\n event: 'inspectElement',\n payload: {\n id,\n rendererID: rendererId,\n requestID: requestId,\n forceFullData: true,\n path: null,\n },\n }));\n\n // Timeout after 5s\n setTimeout(() => {\n this.store.resolveInspectCallback(requestId, null);\n }, 5000);\n });\n }\n\n detach(): void {\n this.ws?.close();\n this.ws = null;\n this.store.connected = false;\n }\n}\n","/**\n * pty-session.ts — PTY session manager with headless terminal emulator\n *\n * Spawns processes in a pseudo-terminal, maintains a virtual screen buffer\n * via xterm-headless, and provides screenshot/input capabilities.\n */\n\nimport * as pty from 'node-pty';\nimport xtermPkg from '@xterm/headless';\nconst { Terminal } = xtermPkg;\nimport unicode11Pkg from '@xterm/addon-unicode11';\nconst { Unicode11Addon } = unicode11Pkg;\n\nexport interface PtySessionOptions {\n command: string;\n args?: string[];\n cwd?: string;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n}\n\nexport interface PtySessionInfo {\n id: string;\n command: string;\n pid: number;\n cols: number;\n rows: number;\n running: boolean;\n}\n\nexport class PtySession {\n readonly id: string;\n readonly command: string;\n private ptyProcess: pty.IPty;\n private terminal: InstanceType<typeof Terminal>;\n private _running = true;\n private exitCode: number | null = null;\n readonly cols: number;\n readonly rows: number;\n\n constructor(id: string, options: PtySessionOptions) {\n this.id = id;\n this.command = options.command;\n this.cols = options.cols ?? 120;\n this.rows = options.rows ?? 40;\n\n // Create headless terminal emulator\n this.terminal = new Terminal({\n cols: this.cols,\n rows: this.rows,\n allowProposedApi: true,\n });\n const unicode11 = new Unicode11Addon();\n this.terminal.loadAddon(unicode11);\n this.terminal.unicode.activeVersion = '11';\n\n // Merge environment\n const env = { ...process.env, ...options.env } as Record<string, string>;\n // Ensure TERM is set for proper PTY behavior\n if (!env.TERM) env.TERM = 'xterm-256color';\n // Force color support\n if (!env.FORCE_COLOR) env.FORCE_COLOR = '1';\n // Set COLUMNS/LINES for apps that check them\n env.COLUMNS = String(this.cols);\n env.LINES = String(this.rows);\n\n // Always run through shell for PATH resolution and command parsing\n const shell = process.env.SHELL || '/bin/bash';\n const shellArgs = ['-c', options.command];\n\n // Spawn PTY process via shell\n this.ptyProcess = pty.spawn(shell, shellArgs, {\n name: 'xterm-256color',\n cols: this.cols,\n rows: this.rows,\n cwd: options.cwd ?? process.cwd(),\n env,\n });\n\n // Pipe PTY output to headless terminal\n this.ptyProcess.onData((data) => {\n this.terminal.write(data);\n });\n\n this.ptyProcess.onExit(({ exitCode }) => {\n this._running = false;\n this.exitCode = exitCode;\n });\n }\n\n /** Simple shell-like string splitting (handles quotes) */\n private shellSplit(cmd: string): string[] {\n const parts: string[] = [];\n let current = '';\n let inSingle = false;\n let inDouble = false;\n\n for (const ch of cmd) {\n if (ch === \"'\" && !inDouble) { inSingle = !inSingle; continue; }\n if (ch === '\"' && !inSingle) { inDouble = !inDouble; continue; }\n if (ch === ' ' && !inSingle && !inDouble) {\n if (current) parts.push(current);\n current = '';\n continue;\n }\n current += ch;\n }\n if (current) parts.push(current);\n return parts;\n }\n\n get pid(): number {\n return this.ptyProcess.pid;\n }\n\n get running(): boolean {\n return this._running;\n }\n\n get info(): PtySessionInfo {\n return {\n id: this.id,\n command: this.command,\n pid: this.ptyProcess.pid,\n cols: this.cols,\n rows: this.rows,\n running: this._running,\n };\n }\n\n /** Capture current screen content as text */\n screenshot(options?: { stripAnsi?: boolean; includeCursor?: boolean }): string {\n const buffer = this.terminal.buffer.active;\n const lines: string[] = [];\n\n for (let i = 0; i < this.rows; i++) {\n const line = buffer.getLine(i);\n if (line) {\n lines.push(line.translateToString(true));\n }\n }\n\n // Trim trailing empty lines\n while (lines.length > 0 && lines[lines.length - 1]!.trim() === '') {\n lines.pop();\n }\n\n let text = lines.join('\\n');\n\n if (options?.stripAnsi) {\n text = text.replace(/\\x1b\\[[0-9;]*[a-zA-Z]/g, '');\n }\n\n return text;\n }\n\n /** Send key press to the PTY */\n press(key: string): void {\n const seq = this.keyToSequence(key);\n this.ptyProcess.write(seq);\n }\n\n /** Type text character by character */\n type(text: string): void {\n this.ptyProcess.write(text);\n }\n\n /** Scroll the terminal viewport */\n scroll(direction: 'up' | 'down', amount = 1): void {\n for (let i = 0; i < amount; i++) {\n if (direction === 'up') {\n this.ptyProcess.write('\\x1b[5~'); // Page Up\n } else {\n this.ptyProcess.write('\\x1b[6~'); // Page Down\n }\n }\n }\n\n /** Resize the terminal */\n resize(cols: number, rows: number): void {\n this.ptyProcess.resize(cols, rows);\n this.terminal.resize(cols, rows);\n }\n\n /** Wait for text to appear on screen */\n async wait(text: string, timeoutMs = 30000): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n const screen = this.screenshot();\n if (screen.includes(text)) return true;\n await new Promise(r => setTimeout(r, 200));\n }\n return false;\n }\n\n /** Kill the PTY process */\n kill(signal: string = 'SIGTERM'): void {\n try {\n this.ptyProcess.kill(signal);\n } catch {\n // already dead\n }\n this._running = false;\n }\n\n /** Clean up resources */\n dispose(): void {\n this.kill();\n this.terminal.dispose();\n }\n\n /** Convert key name to terminal escape sequence */\n private keyToSequence(key: string): string {\n const keyMap: Record<string, string> = {\n 'Enter': '\\r',\n 'Return': '\\r',\n 'Tab': '\\t',\n 'Escape': '\\x1b',\n 'Backspace': '\\x7f',\n 'Delete': '\\x1b[3~',\n 'Space': ' ',\n 'ArrowUp': '\\x1b[A',\n 'ArrowDown': '\\x1b[B',\n 'ArrowRight': '\\x1b[C',\n 'ArrowLeft': '\\x1b[D',\n 'Home': '\\x1b[H',\n 'End': '\\x1b[F',\n 'PageUp': '\\x1b[5~',\n 'PageDown': '\\x1b[6~',\n 'Insert': '\\x1b[2~',\n 'F1': '\\x1bOP',\n 'F2': '\\x1bOQ',\n 'F3': '\\x1bOR',\n 'F4': '\\x1bOS',\n 'F5': '\\x1b[15~',\n 'F6': '\\x1b[17~',\n 'F7': '\\x1b[18~',\n 'F8': '\\x1b[19~',\n 'F9': '\\x1b[20~',\n 'F10': '\\x1b[21~',\n 'F11': '\\x1b[23~',\n 'F12': '\\x1b[24~',\n 'Ctrl-c': '\\x03',\n 'Ctrl-d': '\\x04',\n 'Ctrl-z': '\\x1a',\n 'Ctrl-l': '\\x0c',\n 'Ctrl-a': '\\x01',\n 'Ctrl-e': '\\x05',\n 'Ctrl-k': '\\x0b',\n 'Ctrl-u': '\\x15',\n };\n\n return keyMap[key] ?? key;\n }\n}\n","/**\n * session-manager.ts — Manages multiple PTY sessions\n */\n\nimport { PtySession, type PtySessionOptions, type PtySessionInfo } from './pty-session.js';\n\nexport class SessionManager {\n private sessions = new Map<string, PtySession>();\n\n create(id: string, options: PtySessionOptions): PtySessionInfo {\n // Kill existing session with same ID\n if (this.sessions.has(id)) {\n this.sessions.get(id)!.dispose();\n }\n\n const session = new PtySession(id, options);\n this.sessions.set(id, session);\n return session.info;\n }\n\n get(id: string): PtySession | undefined {\n return this.sessions.get(id);\n }\n\n list(): PtySessionInfo[] {\n return [...this.sessions.values()].map(s => s.info);\n }\n\n kill(id: string): boolean {\n const session = this.sessions.get(id);\n if (!session) return false;\n session.dispose();\n this.sessions.delete(id);\n return true;\n }\n\n killAll(): void {\n for (const session of this.sessions.values()) {\n session.dispose();\n }\n this.sessions.clear();\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getLogPath,
4
+ getPidPath,
5
+ getSocketPath,
6
+ isDaemonRunning,
7
+ sendIpcRequest,
8
+ startDaemon
9
+ } from "./chunk-UV6LYAWB.js";
10
+ export {
11
+ getLogPath,
12
+ getPidPath,
13
+ getSocketPath,
14
+ isDaemonRunning,
15
+ sendIpcRequest,
16
+ startDaemon
17
+ };
18
+ //# sourceMappingURL=daemon-27VEN2X5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "tui-devtools",
3
+ "version": "0.1.0",
4
+ "description": "All-in-one TUI automation + DevTools — run, screenshot, interact, and inspect React component trees in terminal apps. Built for AI agents.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/seongsu-kang/tui-devtools.git"
8
+ },
9
+ "homepage": "https://github.com/seongsu-kang/tui-devtools#readme",
10
+ "bugs": {
11
+ "url": "https://github.com/seongsu-kang/tui-devtools/issues"
12
+ },
13
+ "type": "module",
14
+ "bin": {
15
+ "tui-devtools": "./dist/bin/tui-devtools.js"
16
+ },
17
+ "main": "./dist/src/index.js",
18
+ "types": "./dist/src/index.d.ts",
19
+ "scripts": {
20
+ "build": "tsup",
21
+ "dev": "tsx bin/tui-devtools.ts",
22
+ "postinstall": "chmod +x node_modules/node-pty/prebuilds/darwin-*/spawn-helper 2>/dev/null || true",
23
+ "prepublishOnly": "npm run build"
24
+ },
25
+ "keywords": [
26
+ "tui",
27
+ "devtools",
28
+ "ink",
29
+ "react",
30
+ "terminal",
31
+ "debugging",
32
+ "ai-agent",
33
+ "pty",
34
+ "automation",
35
+ "screenshot",
36
+ "testing"
37
+ ],
38
+ "author": "seongsu-kang",
39
+ "license": "MIT",
40
+ "engines": {
41
+ "node": ">=18"
42
+ },
43
+ "dependencies": {
44
+ "@xterm/addon-unicode11": "^0.9.0",
45
+ "@xterm/headless": "^6.0.0",
46
+ "commander": "^12.0.0",
47
+ "node-pty": "^1.1.0",
48
+ "ws": "^8.16.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^22.0.0",
52
+ "@types/ws": "^8.5.0",
53
+ "tsup": "^8.0.0",
54
+ "tsx": "^4.0.0",
55
+ "typescript": "^5.5.0"
56
+ }
57
+ }