next-ai-editor 0.1.1 → 0.1.2

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.
Files changed (50) hide show
  1. package/dist/{AIEditorProvider-D-w9-GZb.js → AIEditorProvider-CFFnEtEB.js} +849 -402
  2. package/dist/AIEditorProvider-CFFnEtEB.js.map +1 -0
  3. package/dist/{AIEditorProvider-Bs9zUVrL.cjs → AIEditorProvider-CmiACRfw.cjs} +825 -378
  4. package/dist/AIEditorProvider-CmiACRfw.cjs.map +1 -0
  5. package/dist/client/AIEditorProvider.d.ts +8 -16
  6. package/dist/client/AIEditorProvider.d.ts.map +1 -1
  7. package/dist/client/fiber-utils.d.ts +35 -0
  8. package/dist/client/fiber-utils.d.ts.map +1 -0
  9. package/dist/client/index.d.ts +1 -1
  10. package/dist/client/index.d.ts.map +1 -1
  11. package/dist/client/query-params.d.ts +9 -0
  12. package/dist/client/query-params.d.ts.map +1 -0
  13. package/dist/client.cjs +1 -1
  14. package/dist/client.js +1 -1
  15. package/dist/{index-BFa7H-uO.js → index-3OMXRwpD.js} +601 -224
  16. package/dist/index-3OMXRwpD.js.map +1 -0
  17. package/dist/{index-DnoYi4f8.cjs → index-9QODCOgD.cjs} +595 -218
  18. package/dist/index-9QODCOgD.cjs.map +1 -0
  19. package/dist/index.cjs +6 -2
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.js +14 -10
  22. package/dist/path-utils-Bai2xKx9.js +36 -0
  23. package/dist/path-utils-Bai2xKx9.js.map +1 -0
  24. package/dist/path-utils-DYzEWUGy.cjs +35 -0
  25. package/dist/path-utils-DYzEWUGy.cjs.map +1 -0
  26. package/dist/server/handlers/edit.d.ts.map +1 -1
  27. package/dist/server/handlers/index.d.ts +1 -0
  28. package/dist/server/handlers/index.d.ts.map +1 -1
  29. package/dist/server/handlers/read.d.ts.map +1 -1
  30. package/dist/server/handlers/resolve.d.ts.map +1 -1
  31. package/dist/server/handlers/suggestions.d.ts +3 -0
  32. package/dist/server/handlers/suggestions.d.ts.map +1 -0
  33. package/dist/server/index.d.ts +1 -0
  34. package/dist/server/index.d.ts.map +1 -1
  35. package/dist/server/utils/ast.d.ts +10 -0
  36. package/dist/server/utils/ast.d.ts.map +1 -1
  37. package/dist/server/utils/source-map.d.ts +5 -0
  38. package/dist/server/utils/source-map.d.ts.map +1 -1
  39. package/dist/server.cjs +5 -1
  40. package/dist/server.cjs.map +1 -1
  41. package/dist/server.js +13 -9
  42. package/dist/shared/path-utils.d.ts +24 -0
  43. package/dist/shared/path-utils.d.ts.map +1 -0
  44. package/dist/shared/types.d.ts +30 -0
  45. package/dist/shared/types.d.ts.map +1 -1
  46. package/package.json +1 -1
  47. package/dist/AIEditorProvider-Bs9zUVrL.cjs.map +0 -1
  48. package/dist/AIEditorProvider-D-w9-GZb.js.map +0 -1
  49. package/dist/index-BFa7H-uO.js.map +0 -1
  50. package/dist/index-DnoYi4f8.cjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"AIEditorProvider-D-w9-GZb.js","sources":["../src/shared/storage.ts","../src/client/AIEditorProvider.tsx"],"sourcesContent":["// =============================================================================\n// FILE: lib/ai-editor-storage.ts\n// Session storage management for AI editor using localStorage\n// =============================================================================\n\nimport type { ElementContext, PersistedSession } from \"./types\";\n\n// Re-export types for convenience\nexport type { ElementContext, PersistedSession };\n\n// =============================================================================\n// STORAGE UTILITY CLASS\n// =============================================================================\n\nexport class AIEditorStorage {\n private static readonly STORAGE_PREFIX = \"ai-editor:session:\";\n private static readonly VERSION = \"1.0.0\";\n private static readonly MAX_STORAGE_SIZE = 5 * 1024 * 1024; // 5MB\n\n /**\n * Generate storage key from file path and component name\n * Format: \"ai-editor:session:components/Header.tsx#Header\"\n */\n static getSessionKey(filePath: string, componentName: string): string {\n // Normalize path separators\n const normalizedPath = filePath.replace(/\\\\/g, \"/\");\n return `${this.STORAGE_PREFIX}${normalizedPath}#${componentName}`;\n }\n\n /**\n * Save session to localStorage\n */\n static saveSession(session: PersistedSession): boolean {\n try {\n const key = this.getSessionKey(\n session.sourceLocation.filePath,\n session.sourceLocation.componentName\n );\n\n // Check storage size before saving\n if (this.getStorageSize() > this.MAX_STORAGE_SIZE) {\n console.warn(\"Storage size exceeded, pruning old sessions...\");\n this.pruneOldSessions(7 * 24 * 60 * 60 * 1000); // 7 days\n }\n\n const serialized = JSON.stringify(session);\n localStorage.setItem(key, serialized);\n return true;\n } catch (e) {\n if (e instanceof Error && e.name === \"QuotaExceededError\") {\n console.error(\"localStorage quota exceeded\");\n // Try pruning and retry\n this.pruneOldSessions(7 * 24 * 60 * 60 * 1000);\n try {\n const key = this.getSessionKey(\n session.sourceLocation.filePath,\n session.sourceLocation.componentName\n );\n const serialized = JSON.stringify(session);\n localStorage.setItem(key, serialized);\n return true;\n } catch {\n return false;\n }\n }\n console.error(\"Failed to save session:\", e);\n return false;\n }\n }\n\n /**\n * Load session by filePath + componentName\n */\n static loadSession(\n filePath: string,\n componentName: string\n ): PersistedSession | null {\n try {\n const key = this.getSessionKey(filePath, componentName);\n const stored = localStorage.getItem(key);\n\n if (!stored) return null;\n\n const session = JSON.parse(stored) as PersistedSession;\n\n // Validate schema\n if (!session.version || !session.sourceLocation || !session.editHistory) {\n console.warn(\"Invalid session schema, removing corrupted data\");\n localStorage.removeItem(key);\n return null;\n }\n\n return session;\n } catch (e) {\n console.error(\"Failed to load session:\", e);\n // Remove corrupted data\n const key = this.getSessionKey(filePath, componentName);\n localStorage.removeItem(key);\n return null;\n }\n }\n\n /**\n * Delete specific session\n */\n static deleteSession(filePath: string, componentName: string): void {\n try {\n const key = this.getSessionKey(filePath, componentName);\n localStorage.removeItem(key);\n } catch (e) {\n console.error(\"Failed to delete session:\", e);\n }\n }\n\n /**\n * Get all session keys\n */\n static getAllSessionKeys(): string[] {\n const keys: string[] = [];\n try {\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(this.STORAGE_PREFIX)) {\n keys.push(key);\n }\n }\n } catch (e) {\n console.error(\"Failed to get session keys:\", e);\n }\n return keys;\n }\n\n /**\n * Clear all sessions\n */\n static clearAllSessions(): void {\n try {\n const keys = this.getAllSessionKeys();\n keys.forEach((key) => localStorage.removeItem(key));\n console.log(`Cleared ${keys.length} session(s)`);\n } catch (e) {\n console.error(\"Failed to clear sessions:\", e);\n }\n }\n\n /**\n * Get total storage usage in bytes\n */\n static getStorageSize(): number {\n let total = 0;\n try {\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(this.STORAGE_PREFIX)) {\n const value = localStorage.getItem(key);\n if (value) {\n // Approximate size: 2 bytes per character in UTF-16\n total += (key.length + value.length) * 2;\n }\n }\n }\n } catch (e) {\n console.error(\"Failed to calculate storage size:\", e);\n }\n return total;\n }\n\n /**\n * Remove sessions older than maxAge milliseconds\n */\n static pruneOldSessions(maxAge: number): void {\n try {\n const now = Date.now();\n const keys = this.getAllSessionKeys();\n\n keys.forEach((key) => {\n const value = localStorage.getItem(key);\n if (!value) return;\n\n try {\n const session = JSON.parse(value) as PersistedSession;\n const age = now - session.lastModified;\n\n if (age > maxAge) {\n console.log(`Pruning old session: ${key} (age: ${Math.round(age / (24 * 60 * 60 * 1000))} days)`);\n localStorage.removeItem(key);\n }\n } catch (e) {\n // Corrupted data, remove it\n console.warn(`Removing corrupted session: ${key}`);\n localStorage.removeItem(key);\n }\n });\n } catch (e) {\n console.error(\"Failed to prune sessions:\", e);\n }\n }\n\n /**\n * Compute SHA-256 hash of file content using Web Crypto API\n */\n static async hashFileContent(content: string): Promise<string> {\n try {\n // Use Web Crypto API (available in browsers)\n const encoder = new TextEncoder();\n const data = encoder.encode(content);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n\n // Convert buffer to hex string\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n return hashHex;\n } catch (e) {\n console.error(\"Failed to hash content:\", e);\n // Fallback: use simple hash for consistency\n return this.simpleHash(content);\n }\n }\n\n /**\n * Simple hash fallback (for environments without Web Crypto API)\n */\n private static simpleHash(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32-bit integer\n }\n return hash.toString(16);\n }\n\n /**\n * Get most recently modified session\n */\n static getLastActiveSession(): PersistedSession | null {\n try {\n const keys = this.getAllSessionKeys();\n if (keys.length === 0) return null;\n\n let latestSession: PersistedSession | null = null;\n let latestTime = 0;\n\n keys.forEach((key) => {\n const value = localStorage.getItem(key);\n if (!value) return;\n\n try {\n const session = JSON.parse(value) as PersistedSession;\n\n // Validate schema\n if (!session.version || !session.sourceLocation || !session.editHistory) {\n console.warn(`Skipping invalid session: ${key}`);\n return;\n }\n\n if (session.lastModified > latestTime) {\n latestTime = session.lastModified;\n latestSession = session;\n }\n } catch (e) {\n console.warn(`Skipping corrupted session: ${key}`);\n }\n });\n\n return latestSession;\n } catch (e) {\n console.error(\"Failed to get last active session:\", e);\n return null;\n }\n }\n}\n","\"use client\";\n\nimport React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useEffect,\n ReactNode,\n} from \"react\";\nimport { Prism as SyntaxHighlighter } from \"react-syntax-highlighter\";\nimport { vscDarkPlus, vs } from \"react-syntax-highlighter/dist/esm/styles/prism\";\nimport { AIEditorStorage, type PersistedSession } from \"../shared/storage\";\n\n// =============================================================================\n// FEATURE FLAGS\n// =============================================================================\n\nconst ENABLE_SESSION_PERSISTENCE = false; // TODO: Enable when fully tested\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface ElementContext {\n tagName: string;\n textContent?: string;\n className?: string;\n key?: string;\n nthOfType?: number;\n props?: Record<string, any>;\n}\n\nexport interface SourceLocation {\n filePath: string;\n lineNumber: number;\n columnNumber: number;\n componentName: string;\n elementContext?: ElementContext;\n debugStack?: string; // Raw _debugStack for server-side source map resolution\n}\n\ninterface ResolvedSourceInfo {\n filePath: string;\n lineNumber: number;\n columnNumber: number;\n}\n\nconst sourceResolutionCache = new Map<string, ResolvedSourceInfo>();\nconst inflightSourceResolutions = new Map<\n string,\n Promise<ResolvedSourceInfo | null>\n>();\n\nfunction inferComponentNameFromPath(filePath: string): string {\n // Extract component name from file path\n // e.g., \"components/ProductCard.tsx\" -> \"ProductCard\"\n const fileName = filePath.split(\"/\").pop() || \"\";\n const nameWithoutExt = fileName.replace(/\\.(tsx?|jsx?)$/, \"\");\n return nameWithoutExt.charAt(0).toUpperCase() + nameWithoutExt.slice(1);\n}\n\nasync function resolveSourceLocation(\n source: SourceLocation,\n): Promise<SourceLocation | null> {\n if (typeof window === \"undefined\" || process.env.NODE_ENV !== \"development\") {\n return null;\n }\n\n // Need debugStack to resolve\n if (!source.debugStack) {\n console.warn(\"No debugStack available for resolution:\", source);\n return null;\n }\n\n const cacheKey = source.debugStack;\n const cached = sourceResolutionCache.get(cacheKey);\n if (cached) {\n const resolved = { ...source, ...cached };\n // If component name is Unknown, infer from resolved file path\n if (resolved.componentName === \"Unknown\" && resolved.filePath) {\n resolved.componentName = inferComponentNameFromPath(resolved.filePath);\n }\n return resolved;\n }\n\n let inflight = inflightSourceResolutions.get(cacheKey);\n if (!inflight) {\n inflight = fetch(\"/api/ai-editor/resolve\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ debugStack: cacheKey }),\n })\n .then(async (res) => {\n if (!res.ok) {\n const errorText = await res.text();\n console.error(\n `Resolve API error ${res.status}:`,\n errorText,\n \"for stack:\",\n cacheKey.substring(0, 200),\n );\n // Fallback: Try to infer file path from component name\n return inferFilePathFromComponentName(source.componentName);\n }\n const data = await res.json();\n if (data?.success && data.filePath && data.lineNumber) {\n const resolved: ResolvedSourceInfo = {\n filePath: data.filePath,\n lineNumber: data.lineNumber,\n columnNumber:\n typeof data.columnNumber === \"number\"\n ? data.columnNumber\n : source.columnNumber,\n };\n sourceResolutionCache.set(cacheKey, resolved);\n return resolved;\n }\n console.warn(\"Resolve API returned unsuccessful response:\", data);\n // Fallback: Try to infer file path from component name\n return inferFilePathFromComponentName(source.componentName);\n })\n .catch((err) => {\n console.error(\"Error calling resolve API:\", err);\n // Fallback: Try to infer file path from component name\n return inferFilePathFromComponentName(source.componentName);\n })\n .finally(() => {\n inflightSourceResolutions.delete(cacheKey);\n });\n\n inflightSourceResolutions.set(cacheKey, inflight);\n }\n\n const resolvedInfo = await inflight;\n if (!resolvedInfo) return null;\n\n const resolved = {\n ...source,\n filePath: resolvedInfo.filePath,\n lineNumber: resolvedInfo.lineNumber,\n columnNumber: resolvedInfo.columnNumber,\n };\n\n // If component name is Unknown, infer from resolved file path\n if (resolved.componentName === \"Unknown\" && resolved.filePath) {\n resolved.componentName = inferComponentNameFromPath(resolved.filePath);\n }\n\n return resolved;\n}\n\nasync function inferFilePathFromComponentName(\n componentName: string,\n): Promise<ResolvedSourceInfo | null> {\n if (!componentName || componentName === \"Unknown\") return null;\n\n // Try common locations for components\n const possiblePaths = [\n `components/${componentName}.tsx`,\n `components/${componentName}.jsx`,\n `app/${componentName}.tsx`,\n `app/${componentName}.jsx`,\n `src/components/${componentName}.tsx`,\n `src/components/${componentName}.jsx`,\n ];\n\n // Check which file exists by trying to read it\n for (const tryPath of possiblePaths) {\n try {\n const response = await fetch(\n `/api/ai-editor/absolute-path?path=${encodeURIComponent(tryPath)}`,\n );\n if (response.ok) {\n const data = await response.json();\n if (data.success) {\n console.log(\n `Inferred file path for ${componentName}: ${tryPath}`,\n );\n return {\n filePath: tryPath,\n lineNumber: 1,\n columnNumber: 0,\n };\n }\n }\n } catch (err) {\n // Continue trying other paths\n }\n }\n\n console.warn(`Could not infer file path for component: ${componentName}`);\n return null;\n}\n\ninterface FiberNode {\n tag: number;\n type: any;\n return: FiberNode | null;\n key: string | null;\n memoizedProps?: any;\n pendingProps?: any;\n _debugSource?: {\n fileName: string;\n lineNumber: number;\n columnNumber?: number;\n };\n _debugOwner?: FiberNode;\n _debugInfo?: any;\n _debugStack?: any;\n}\n\ninterface EditHistoryItem {\n id: string; // Unique identifier for each edit\n suggestion: string;\n success: boolean;\n error?: string;\n timestamp: number;\n // Undo support\n fileSnapshot?: string; // File content BEFORE this edit\n modifiedLines?: {\n // Lines that were changed\n start: number;\n end: number;\n };\n generatedCode?: string; // AI-generated code\n}\n\ninterface EditorContextType {\n isEnabled: boolean;\n setEnabled: (enabled: boolean) => void;\n selectedSource: SourceLocation | null;\n setSelectedSource: (el: SourceLocation | null) => void;\n selectedDOMElement: Element | null;\n isLoading: boolean;\n setIsLoading: (loading: boolean) => void;\n editHistory: EditHistoryItem[];\n setEditHistory: React.Dispatch<React.SetStateAction<EditHistoryItem[]>>;\n submitEdit: (\n suggestion: string,\n ) => Promise<{ success: boolean; error?: string }>;\n}\n\n// =============================================================================\n// CONTEXT\n// =============================================================================\n\nconst EditorContext = createContext<EditorContextType | null>(null);\n\nexport function useAIEditor() {\n const ctx = useContext(EditorContext);\n if (!ctx) throw new Error(\"useAIEditor must be used within AIEditorProvider\");\n return ctx;\n}\n\n// =============================================================================\n// FIBER UTILITIES\n// =============================================================================\n\nfunction getFiberFromElement(element: Element): FiberNode | null {\n const key = Object.keys(element).find(\n (k) =>\n k.startsWith(\"__reactFiber$\") || k.startsWith(\"__reactInternalInstance$\"),\n );\n return key ? (element as any)[key] : null;\n}\n\nfunction getComponentName(fiber: FiberNode | null): string {\n if (!fiber) return \"Unknown\";\n const type = fiber.type;\n if (typeof type === \"string\") return type;\n if (typeof type === \"function\")\n return type.displayName || type.name || \"Anonymous\";\n if (type?.displayName) return type.displayName;\n if (type?.render?.name) return type.render.name;\n return \"Unknown\";\n}\n\nfunction isUserComponent(fiber: FiberNode): boolean {\n if (fiber.tag === 5 || fiber.tag === 6 || fiber.tag === 3) return false;\n const type = fiber.type;\n if (!type || typeof type === \"string\") return false;\n return true;\n}\n\n// =============================================================================\n// ELEMENT CONTEXT CAPTURE\n// =============================================================================\n\nfunction captureElementContext(\n element: Element,\n fiber: FiberNode | null,\n): ElementContext {\n const tagName = element.tagName.toLowerCase();\n\n // Text content (direct text only, truncated)\n let textContent: string | undefined;\n const directText = Array.from(element.childNodes)\n .filter((n) => n.nodeType === Node.TEXT_NODE)\n .map((n) => n.textContent?.trim())\n .filter(Boolean)\n .join(\" \");\n\n if (directText) {\n textContent = directText.slice(0, 50);\n } else if (element.textContent) {\n textContent = element.textContent.trim().slice(0, 50);\n }\n\n // Class name\n const className =\n typeof element.className === \"string\"\n ? element.className.slice(0, 100)\n : undefined;\n\n // Count nth of type within component\n const nthOfType = countNthOfType(element, tagName);\n\n // React key\n const key = fiber?.key ? String(fiber.key) : undefined;\n\n // Identifying props\n const props = extractProps(fiber);\n\n return { tagName, textContent, className, key, nthOfType, props };\n}\n\nfunction countNthOfType(element: Element, tagName: string): number {\n let boundary: Element | null = element.parentElement;\n\n // Find component boundary\n while (boundary) {\n const fiber = getFiberFromElement(boundary);\n if (fiber && isUserComponent(fiber)) break;\n boundary = boundary.parentElement;\n }\n\n if (!boundary) boundary = element.parentElement;\n if (!boundary) return 1;\n\n // Get all matching elements INCLUDING the boundary itself\n const sameTagElements: Element[] = [];\n\n // Check if boundary itself matches\n if (boundary.tagName.toLowerCase() === tagName.toLowerCase()) {\n sameTagElements.push(boundary);\n }\n\n // Add all descendants that match\n sameTagElements.push(...Array.from(boundary.querySelectorAll(tagName)));\n\n let count = 1;\n for (const el of sameTagElements) {\n if (el === element) break;\n count++;\n }\n\n console.log(\n `[countNthOfType] tagName=${tagName}, found ${sameTagElements.length} elements (including boundary), this is #${count}`,\n );\n\n return count;\n}\n\nfunction extractProps(\n fiber: FiberNode | null,\n): Record<string, any> | undefined {\n if (!fiber) return undefined;\n\n const fiberProps = fiber.memoizedProps || fiber.pendingProps;\n if (!fiberProps || typeof fiberProps !== \"object\") return undefined;\n\n const props: Record<string, any> = {};\n const identifyingKeys = [\n \"id\",\n \"name\",\n \"type\",\n \"href\",\n \"src\",\n \"alt\",\n \"role\",\n \"aria-label\",\n \"data-testid\",\n ];\n\n for (const key of identifyingKeys) {\n if (key in fiberProps && typeof fiberProps[key] === \"string\") {\n props[key] = fiberProps[key];\n }\n }\n\n if (fiberProps.style && typeof fiberProps.style === \"object\") {\n props._styleKeys = Object.keys(fiberProps.style).slice(0, 5);\n }\n\n return Object.keys(props).length > 0 ? props : undefined;\n}\n\n// =============================================================================\n// SOURCE LOCATION FINDER\n// =============================================================================\n\nfunction findSourceFromFiber(\n fiber: FiberNode | null,\n): Omit<SourceLocation, \"elementContext\"> | null {\n if (!fiber) return null;\n\n let current: FiberNode | null = fiber;\n const visited = new Set<FiberNode>();\n\n while (current && !visited.has(current)) {\n visited.add(current);\n\n // Try to get source from various debug properties\n const sourceData =\n current._debugSource ||\n extractFromDebugStack(current) ||\n extractFromDebugOwner(current);\n\n if (sourceData?.fileName) {\n const filePath = cleanPath(sourceData.fileName);\n\n if (!shouldSkip(filePath)) {\n // Walk up to find the nearest user component (skip Next.js internals)\n let componentFiber: FiberNode | null = current;\n while (componentFiber) {\n if (isUserComponent(componentFiber)) {\n const componentName = getComponentName(componentFiber);\n\n // Skip Next.js internal components\n const isNextJSInternal = [\n \"Segment\",\n \"Boundary\",\n \"Router\",\n \"Handler\",\n \"Context\",\n \"Layout\",\n \"Template\",\n \"Scroll\",\n \"Focus\",\n \"Loading\",\n \"Error\",\n ].some((pattern) => componentName.includes(pattern));\n\n if (!isNextJSInternal) {\n // Capture the raw _debugStack for server-side source map resolution\n const rawDebugStack = current._debugStack\n ? String(current._debugStack.stack || current._debugStack)\n : undefined;\n\n return {\n filePath,\n lineNumber: sourceData.lineNumber || 1,\n columnNumber: sourceData.columnNumber || 0,\n componentName,\n debugStack: rawDebugStack,\n };\n }\n }\n componentFiber =\n componentFiber.return || componentFiber._debugOwner || null;\n }\n }\n }\n\n current = current.return || current._debugOwner || null;\n }\n\n return null;\n}\n\nfunction extractFromDebugStack(\n fiber: FiberNode,\n): { fileName: string; lineNumber: number; columnNumber?: number } | null {\n const stack = (fiber as any)._debugStack;\n if (!stack) return null;\n\n const stackStr = stack.stack || String(stack);\n const frames = stackStr.split(\"\\n\");\n\n const skipPatterns = [\n \"node_modules\",\n \"SegmentViewNode\",\n \"LayoutRouter\",\n \"ErrorBoundary\",\n \"fakeJSXCallSite\",\n ];\n\n for (const frame of frames) {\n if (skipPatterns.some((p) => frame.includes(p))) continue;\n\n // Match: at Name (path:line:col)\n const match = frame.match(/at\\s+(\\w+)\\s+\\((.+?):(\\d+):(\\d+)\\)?$/);\n if (match) {\n const fileName = cleanPath(match[2].replace(/\\?[^:]*$/, \"\"));\n if (!shouldSkip(fileName)) {\n return {\n fileName,\n lineNumber: parseInt(match[3], 10),\n columnNumber: parseInt(match[4], 10),\n };\n }\n }\n }\n return null;\n}\n\nfunction extractFromDebugOwner(\n fiber: FiberNode,\n): { fileName: string; lineNumber: number; columnNumber?: number } | null {\n const owner = (fiber as any)._debugOwner;\n if (!owner) return null;\n\n if (owner._debugSource?.fileName) {\n return owner._debugSource;\n }\n\n const stack = owner.stack;\n if (Array.isArray(stack) && stack[0]?.fileName) {\n return stack[0];\n }\n\n return null;\n}\n\nfunction cleanPath(p: string): string {\n // With turbopack, preserve the actual file path, only remove protocol prefixes\n // Handle file:// URLs and URL encoding\n let cleaned = p;\n\n // Remove file:// protocol first\n if (cleaned.startsWith(\"file://\")) {\n cleaned = cleaned.replace(/^file:\\/\\//, \"\");\n }\n\n // Decode URL-encoded paths\n try {\n if (cleaned.includes(\"%\")) {\n cleaned = decodeURIComponent(cleaned);\n }\n } catch (e) {\n // If decoding fails, continue with original\n }\n\n // Remove other protocol prefixes\n cleaned = cleaned\n .replace(/^webpack-internal:\\/\\/\\/\\([^)]+\\)\\/\\.\\//, \"\")\n .replace(/^webpack-internal:\\/\\/\\/\\([^)]+\\)\\//, \"\")\n .replace(/^webpack-internal:\\/\\//, \"\")\n .replace(/^webpack:\\/\\/[^/]*\\//, \"\")\n .replace(/^about:\\/\\/React\\/Server\\//, \"\")\n .replace(/^\\([^)]+\\)\\//, \"\")\n .replace(/^\\.\\//, \"\")\n .replace(/\\?.*$/, \"\");\n\n return cleaned;\n}\n\nfunction shouldSkip(p: string): boolean {\n if (!p) return true;\n return [\"node_modules\", \"next/dist\", \"react-dom\", \"ai-editor-provider\"].some(\n (s) => p.includes(s),\n );\n}\n\n// =============================================================================\n// GET SOURCE FROM ELEMENT (Main export)\n// =============================================================================\n\nfunction getSourceFromElement(element: Element): SourceLocation | null {\n // Walk up DOM to find element with fiber\n let current: Element | null = element;\n let fiber: FiberNode | null = null;\n\n while (current && current !== document.body) {\n fiber = getFiberFromElement(current);\n if (fiber) break;\n current = current.parentElement;\n }\n\n if (!fiber) return null;\n\n const source = findSourceFromFiber(fiber);\n if (!source) return null;\n\n // Add element context for precise matching\n const elementContext = captureElementContext(element, fiber);\n\n return { ...source, elementContext };\n}\n\n// Debug helper\nif (typeof window !== \"undefined\") {\n (window as any).__getSource = getSourceFromElement;\n}\n\n// =============================================================================\n// PROVIDER\n// =============================================================================\n\nexport function AIEditorProvider({\n children,\n theme = \"dark\",\n}: {\n children: ReactNode;\n theme?: \"light\" | \"dark\";\n}) {\n const [isEnabled, setEnabled] = useState(false);\n const [selectedSource, setSelectedSource] = useState<SourceLocation | null>(\n null,\n );\n const [selectedDOMElement, setSelectedDOMElement] = useState<Element | null>(\n null,\n );\n const [isLoading, setIsLoading] = useState(false);\n const [editHistory, setEditHistory] = useState<EditHistoryItem[]>([]);\n const [showStaleWarning, setShowStaleWarning] = useState(false);\n const [staleSession, setStaleSession] = useState<PersistedSession | null>(null);\n const [hasActiveSession, setHasActiveSession] = useState(false);\n\n useEffect(() => {\n const handleKey = (e: KeyboardEvent) => {\n if (\n (e.ctrlKey || e.metaKey) &&\n e.shiftKey &&\n e.key.toLowerCase() === \"e\"\n ) {\n e.preventDefault();\n setEnabled((p) => !p);\n }\n };\n window.addEventListener(\"keydown\", handleKey);\n return () => window.removeEventListener(\"keydown\", handleKey);\n }, []);\n\n // Auto-restore last session on mount\n useEffect(() => {\n if (!ENABLE_SESSION_PERSISTENCE) return;\n if (typeof window === \"undefined\") return;\n\n const lastSession = AIEditorStorage.getLastActiveSession();\n if (!lastSession) return;\n\n setHasActiveSession(true);\n\n // Validate session\n fetch(\"/api/ai-editor/validate-session\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n filePath: lastSession.sourceLocation.filePath,\n lastKnownHash: lastSession.fileValidation.lastKnownHash,\n lastKnownSize: lastSession.fileValidation.lastKnownSize,\n }),\n })\n .then((r) => r.json())\n .then((result) => {\n if (!result.isValid) {\n setStaleSession(lastSession);\n setShowStaleWarning(true);\n } else {\n restoreSession(lastSession);\n }\n })\n .catch((err) => {\n console.error(\"Session validation failed:\", err);\n // On error, show warning (safer than auto-restore)\n setStaleSession(lastSession);\n setShowStaleWarning(true);\n });\n }, []);\n\n const restoreSession = useCallback(async (session: PersistedSession) => {\n const sourceLocation = session.sourceLocation;\n\n setSelectedSource(sourceLocation);\n setEditHistory(session.editHistory);\n\n // Trigger async source resolution if needed\n if (sourceLocation.debugStack) {\n const resolved = await resolveSourceLocation(sourceLocation);\n if (resolved) {\n setSelectedSource(resolved);\n }\n }\n }, []);\n\n const handleClearSession = useCallback(() => {\n if (selectedSource) {\n AIEditorStorage.deleteSession(\n selectedSource.filePath,\n selectedSource.componentName\n );\n setHasActiveSession(false);\n setSelectedSource(null);\n setEditHistory([]);\n }\n }, [selectedSource]);\n\n const submitEdit = useCallback(\n async (suggestion: string) => {\n if (!selectedSource)\n return { success: false, error: \"No element selected\" };\n\n setIsLoading(true);\n try {\n const res = await fetch(\"/api/ai-editor/edit\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n filePath: selectedSource.filePath,\n lineNumber: selectedSource.lineNumber,\n componentName: selectedSource.componentName,\n suggestion,\n // NEW: Pass element context for precise matching\n elementContext: selectedSource.elementContext,\n // Pass debugStack for server-side source map resolution\n debugStack: selectedSource.debugStack,\n // Pass edit history for context\n editHistory: editHistory.map((item) => ({\n suggestion: item.suggestion,\n success: item.success,\n })),\n }),\n });\n const result = await res.json();\n\n // Generate unique ID for this edit\n const editId =\n Date.now().toString(36) + Math.random().toString(36).substring(2);\n\n // Create new history item\n const newHistoryItem = {\n id: editId,\n suggestion,\n success: result.success,\n error: result.error,\n timestamp: Date.now(),\n fileSnapshot: result.fileSnapshot,\n generatedCode: result.generatedCode,\n modifiedLines: result.modifiedLines,\n };\n\n // Add to history\n setEditHistory((prev) => [...prev, newHistoryItem]);\n\n // Save session to localStorage\n if (ENABLE_SESSION_PERSISTENCE && selectedSource && result.fileSnapshot) {\n try {\n const hash = await AIEditorStorage.hashFileContent(result.fileSnapshot);\n const session: PersistedSession = {\n sessionId: `${selectedSource.filePath}#${selectedSource.componentName}`,\n version: \"1.0.0\",\n lastModified: Date.now(),\n sourceLocation: selectedSource,\n editHistory: [...editHistory, newHistoryItem],\n fileValidation: {\n lastKnownHash: hash,\n lastKnownSize: result.fileSnapshot.length,\n lastEditTimestamp: Date.now(),\n },\n uiState: {\n currentSuggestion: \"\", // Clear after successful edit\n modalWasOpen: true,\n },\n };\n AIEditorStorage.saveSession(session);\n setHasActiveSession(true);\n } catch (e) {\n console.error(\"Failed to save session:\", e);\n }\n }\n\n return result;\n } catch (err) {\n const error = String(err);\n const editId =\n Date.now().toString(36) + Math.random().toString(36).substring(2);\n setEditHistory((prev) => [\n ...prev,\n {\n id: editId,\n suggestion,\n success: false,\n error,\n timestamp: Date.now(),\n },\n ]);\n return { success: false, error };\n } finally {\n setIsLoading(false);\n }\n },\n [selectedSource, editHistory],\n );\n\n const handleSelect = useCallback(\n (element: Element, source: SourceLocation) => {\n setSelectedDOMElement(element);\n setSelectedSource(source);\n // Clear edit history when selecting a new component\n setEditHistory([]);\n\n resolveSourceLocation(source).then((resolved) => {\n if (resolved) {\n setSelectedSource((prev) => (prev === source ? resolved : prev));\n }\n });\n },\n [setSelectedDOMElement, setSelectedSource],\n );\n\n if (process.env.NODE_ENV !== \"development\") {\n return <>{children}</>;\n }\n\n return (\n <EditorContext.Provider\n value={{\n isEnabled,\n setEnabled,\n selectedSource,\n setSelectedSource,\n selectedDOMElement,\n isLoading,\n setIsLoading,\n editHistory,\n setEditHistory,\n submitEdit,\n }}\n >\n {children}\n {isEnabled && (\n <EditorOverlay\n theme={theme}\n onSelect={handleSelect}\n showStaleWarning={showStaleWarning}\n staleSession={staleSession}\n hasActiveSession={hasActiveSession}\n setShowStaleWarning={setShowStaleWarning}\n setStaleSession={setStaleSession}\n setHasActiveSession={setHasActiveSession}\n restoreSession={restoreSession}\n handleClearSession={handleClearSession}\n />\n )}\n </EditorContext.Provider>\n );\n}\n\n// =============================================================================\n// OVERLAY\n// =============================================================================\n\nfunction EditorOverlay({\n theme,\n onSelect,\n showStaleWarning,\n staleSession,\n hasActiveSession,\n setShowStaleWarning,\n setStaleSession,\n setHasActiveSession,\n restoreSession,\n handleClearSession,\n}: {\n theme: \"light\" | \"dark\";\n onSelect: (el: Element, source: SourceLocation) => void;\n showStaleWarning: boolean;\n staleSession: PersistedSession | null;\n hasActiveSession: boolean;\n setShowStaleWarning: (value: boolean) => void;\n setStaleSession: (value: PersistedSession | null) => void;\n setHasActiveSession: (value: boolean) => void;\n restoreSession: (session: PersistedSession) => void;\n handleClearSession: () => void;\n}) {\n const {\n selectedSource,\n setSelectedSource,\n submitEdit,\n isLoading,\n setIsLoading,\n setEnabled,\n selectedDOMElement,\n editHistory,\n setEditHistory,\n } = useAIEditor();\n const [hoveredSource, setHoveredSource] = useState<SourceLocation | null>(\n null,\n );\n const [hoveredElement, setHoveredElement] = useState<Element | null>(null);\n const [hoveredRect, setHoveredRect] = useState<DOMRect | null>(null);\n const [mousePos, setMousePos] = useState({ x: 0, y: 0 });\n const [isResolvingSource, setIsResolvingSource] = useState(false);\n const [suggestion, setSuggestion] = useState(\"\");\n const [result, setResult] = useState<{\n success: boolean;\n error?: string;\n } | null>(null);\n const [code, setCode] = useState(\"\");\n const [codeLineStart, setCodeLineStart] = useState(1);\n const [targetStartLine, setTargetStartLine] = useState<number | null>(null);\n const [targetEndLine, setTargetEndLine] = useState<number | null>(null);\n const [absolutePath, setAbsolutePath] = useState<string | null>(null);\n const [parsedComponentName, setParsedComponentName] = useState<string | null>(\n null,\n );\n\n const isDark = theme === \"dark\";\n\n // Fetch code preview and absolute path\n useEffect(() => {\n if (selectedSource) {\n const params: Record<string, string> = {\n path: selectedSource.filePath,\n line: String(selectedSource.lineNumber),\n tagName: selectedSource.elementContext?.tagName || \"\",\n nthOfType: String(selectedSource.elementContext?.nthOfType || 0),\n textContent: selectedSource.elementContext?.textContent || \"\",\n className: selectedSource.elementContext?.className || \"\",\n };\n\n // Include debugStack if available for server-side source map resolution\n if (selectedSource.debugStack) {\n params.debugStack = selectedSource.debugStack;\n }\n\n fetch(`/api/ai-editor/read?` + new URLSearchParams(params))\n .then((r) => r.json())\n .then((d) => {\n if (d.success) {\n console.log('[AI Editor] Read response:', {\n lineStart: d.lineStart,\n targetStartLine: d.targetStartLine,\n targetEndLine: d.targetEndLine,\n componentName: d.componentName\n });\n setCode(d.content);\n setCodeLineStart(d.lineStart || 1);\n setTargetStartLine(d.targetStartLine || null);\n setTargetEndLine(d.targetEndLine || null);\n\n // Store component name from parsed code if available\n if (d.componentName) {\n setParsedComponentName(d.componentName);\n }\n }\n })\n .catch(() => {\n setCode(\"// Could not load\");\n setCodeLineStart(1);\n setTargetStartLine(null);\n setTargetEndLine(null);\n });\n\n // Fetch absolute path\n fetch(\n `/api/ai-editor/absolute-path?` +\n new URLSearchParams({ path: selectedSource.filePath }),\n )\n .then((r) => r.json())\n .then((d) => d.success && setAbsolutePath(d.absolutePath))\n .catch(() => setAbsolutePath(null));\n } else {\n setAbsolutePath(null);\n setParsedComponentName(null);\n }\n }, [selectedSource]);\n\n // Mouse tracking\n useEffect(() => {\n let lastEl: Element | null = null;\n let raf: number;\n\n const onMove = (e: MouseEvent) => {\n setMousePos({ x: e.clientX, y: e.clientY });\n if (selectedSource) return;\n\n cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() => {\n const el = document.elementFromPoint(e.clientX, e.clientY);\n if (!el || el.closest(\".ai-editor-ui\") || el === lastEl) return;\n lastEl = el;\n\n const source = getSourceFromElement(el);\n if (source) {\n setHoveredElement(el);\n setHoveredRect(el.getBoundingClientRect());\n\n // Check if this looks like a compiled path that needs resolution\n const isCompiledPath =\n source.filePath.includes(\".next/\") ||\n source.filePath.includes(\"/chunks/\") ||\n source.filePath.startsWith(\"file://\") ||\n (source.filePath.endsWith(\".js\") &&\n (source.filePath.includes(\"/server/\") ||\n source.filePath.includes(\"/static/\")));\n\n if (isCompiledPath && source.debugStack) {\n // Wait for resolution before showing the tooltip\n setIsResolvingSource(true);\n resolveSourceLocation(source)\n .then((resolved) => {\n setIsResolvingSource(false);\n if (resolved) {\n console.log(\"Resolved source location:\", resolved);\n setHoveredSource(resolved);\n } else {\n console.warn(\n \"Failed to resolve source location for:\",\n source,\n );\n // If resolution fails, still show the source (might be a client component)\n setHoveredSource(source);\n }\n })\n .catch((err) => {\n console.error(\"Error resolving source location:\", err);\n setIsResolvingSource(false);\n setHoveredSource(source);\n });\n } else if (isCompiledPath && !source.debugStack) {\n // Compiled path but no debugStack - can't resolve, show as-is\n console.warn(\"Compiled path but no debugStack:\", source);\n setIsResolvingSource(false);\n setHoveredSource(source);\n } else {\n // Not a compiled path, show immediately\n setIsResolvingSource(false);\n setHoveredSource(source);\n }\n } else {\n setHoveredSource(null);\n setHoveredElement(null);\n setHoveredRect(null);\n setIsResolvingSource(false);\n }\n });\n };\n\n const onClick = (e: MouseEvent) => {\n if ((e.target as Element).closest(\".ai-editor-ui\")) return;\n if (hoveredSource && hoveredElement) {\n e.preventDefault();\n e.stopPropagation();\n onSelect(hoveredElement, hoveredSource);\n setSuggestion(\"\");\n setResult(null);\n }\n };\n\n document.addEventListener(\"mousemove\", onMove, { passive: true });\n document.addEventListener(\"click\", onClick, true);\n return () => {\n document.removeEventListener(\"mousemove\", onMove);\n document.removeEventListener(\"click\", onClick, true);\n cancelAnimationFrame(raf);\n };\n }, [hoveredSource, hoveredElement, selectedSource, onSelect]);\n\n const handleSubmit = async () => {\n if (!suggestion.trim()) return;\n const res = await submitEdit(suggestion);\n setResult(res);\n // Don't auto-reload, let user continue editing or manually finish\n if (res.success) {\n setSuggestion(\"\"); // Clear input for next edit\n\n // Refresh code preview to show the updated code\n if (selectedSource) {\n const params: Record<string, string> = {\n path: selectedSource.filePath,\n line: String(selectedSource.lineNumber),\n tagName: selectedSource.elementContext?.tagName || \"\",\n nthOfType: String(selectedSource.elementContext?.nthOfType || 0),\n textContent: selectedSource.elementContext?.textContent || \"\",\n className: selectedSource.elementContext?.className || \"\",\n };\n\n if (selectedSource.debugStack) {\n params.debugStack = selectedSource.debugStack;\n }\n\n fetch(`/api/ai-editor/read?` + new URLSearchParams(params))\n .then((r) => r.json())\n .then((d) => {\n if (d.success) {\n setCode(d.content);\n setCodeLineStart(d.lineStart || 1);\n setTargetStartLine(d.targetStartLine || null);\n setTargetEndLine(d.targetEndLine || null);\n if (d.componentName) {\n setParsedComponentName(d.componentName);\n }\n }\n })\n .catch(console.error);\n }\n\n // Reset result after a delay\n setTimeout(() => setResult(null), 3000);\n }\n };\n\n const handleUndo = async () => {\n if (editHistory.length === 0 || !selectedSource) return;\n\n // Find the last successful edit with a snapshot\n const lastSuccessfulEdit = [...editHistory]\n .reverse()\n .find((edit) => edit.success && edit.fileSnapshot);\n\n if (!lastSuccessfulEdit) {\n console.warn(\"No successful edit with snapshot found to undo\");\n return;\n }\n\n setIsLoading(true);\n try {\n // Call undo endpoint to restore file\n const response = await fetch(\"/api/ai-editor/undo\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n filePath: selectedSource.filePath,\n content: lastSuccessfulEdit.fileSnapshot,\n }),\n });\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error || \"Undo failed\");\n }\n\n // Remove the last successful edit from history\n setEditHistory((prev) => {\n const lastIndex = prev.lastIndexOf(lastSuccessfulEdit);\n return prev.filter((_, idx) => idx !== lastIndex);\n });\n\n // Refresh code preview\n const params: Record<string, string> = {\n path: selectedSource.filePath,\n line: String(selectedSource.lineNumber),\n tagName: selectedSource.elementContext?.tagName || \"\",\n nthOfType: String(selectedSource.elementContext?.nthOfType || 0),\n textContent: selectedSource.elementContext?.textContent || \"\",\n className: selectedSource.elementContext?.className || \"\",\n };\n\n if (selectedSource.debugStack) {\n params.debugStack = selectedSource.debugStack;\n }\n\n fetch(`/api/ai-editor/read?` + new URLSearchParams(params))\n .then((r) => r.json())\n .then((d) => {\n if (d.success) {\n setCode(d.content);\n setCodeLineStart(d.lineStart || 1);\n setTargetStartLine(d.targetStartLine || null);\n setTargetEndLine(d.targetEndLine || null);\n if (d.componentName) {\n setParsedComponentName(d.componentName);\n }\n }\n })\n .catch(console.error);\n\n setResult({ success: true, error: undefined });\n setTimeout(() => setResult(null), 3000);\n } catch (error) {\n console.error(\"Undo error:\", error);\n setResult({ success: false, error: String(error) });\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleRetry = async (editIndex: number) => {\n const editToRetry = editHistory[editIndex];\n if (!editToRetry) return;\n\n // Re-submit the same suggestion\n const res = await submitEdit(editToRetry.suggestion);\n\n // Refresh code preview if successful\n if (res.success && selectedSource) {\n const params: Record<string, string> = {\n path: selectedSource.filePath,\n line: String(selectedSource.lineNumber),\n tagName: selectedSource.elementContext?.tagName || \"\",\n nthOfType: String(selectedSource.elementContext?.nthOfType || 0),\n textContent: selectedSource.elementContext?.textContent || \"\",\n className: selectedSource.elementContext?.className || \"\",\n };\n\n if (selectedSource.debugStack) {\n params.debugStack = selectedSource.debugStack;\n }\n\n fetch(`/api/ai-editor/read?` + new URLSearchParams(params))\n .then((r) => r.json())\n .then((d) => {\n if (d.success) {\n setCode(d.content);\n setCodeLineStart(d.lineStart || 1);\n setTargetStartLine(d.targetStartLine || null);\n setTargetEndLine(d.targetEndLine || null);\n if (d.componentName) {\n setParsedComponentName(d.componentName);\n }\n }\n })\n .catch(console.error);\n }\n };\n\n const handleUndoAndRetry = async () => {\n if (editHistory.length === 0 || !selectedSource) return;\n\n // Find the last successful edit with a snapshot\n const lastSuccessfulEdit = [...editHistory]\n .reverse()\n .find((edit) => edit.success && edit.fileSnapshot);\n\n if (!lastSuccessfulEdit) {\n console.warn(\"No successful edit with snapshot found to undo and retry\");\n return;\n }\n\n setIsLoading(true);\n try {\n // Step 1: Undo the last edit\n const undoResponse = await fetch(\"/api/ai-editor/undo\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n filePath: selectedSource.filePath,\n content: lastSuccessfulEdit.fileSnapshot,\n }),\n });\n\n const undoResult = await undoResponse.json();\n\n if (!undoResult.success) {\n throw new Error(undoResult.error || \"Undo failed\");\n }\n\n // Remove the last successful edit from history\n setEditHistory((prev) => {\n const lastIndex = prev.lastIndexOf(lastSuccessfulEdit);\n return prev.filter((_, idx) => idx !== lastIndex);\n });\n\n // Refresh code preview\n const params: Record<string, string> = {\n path: selectedSource.filePath,\n line: String(selectedSource.lineNumber),\n tagName: selectedSource.elementContext?.tagName || \"\",\n nthOfType: String(selectedSource.elementContext?.nthOfType || 0),\n textContent: selectedSource.elementContext?.textContent || \"\",\n className: selectedSource.elementContext?.className || \"\",\n };\n\n if (selectedSource.debugStack) {\n params.debugStack = selectedSource.debugStack;\n }\n\n await fetch(`/api/ai-editor/read?` + new URLSearchParams(params))\n .then((r) => r.json())\n .then((d) => {\n if (d.success) {\n setCode(d.content);\n setCodeLineStart(d.lineStart || 1);\n setTargetStartLine(d.targetStartLine || null);\n setTargetEndLine(d.targetEndLine || null);\n if (d.componentName) {\n setParsedComponentName(d.componentName);\n }\n }\n })\n .catch(console.error);\n\n // Step 2: Retry the same suggestion\n setIsLoading(true); // Keep loading state\n const retryResult = await submitEdit(lastSuccessfulEdit.suggestion);\n\n // Refresh code preview after retry\n if (retryResult.success && selectedSource) {\n await fetch(`/api/ai-editor/read?` + new URLSearchParams(params))\n .then((r) => r.json())\n .then((d) => {\n if (d.success) {\n setCode(d.content);\n setCodeLineStart(d.lineStart || 1);\n setTargetStartLine(d.targetStartLine || null);\n setTargetEndLine(d.targetEndLine || null);\n if (d.componentName) {\n setParsedComponentName(d.componentName);\n }\n }\n })\n .catch(console.error);\n }\n\n if (retryResult.success) {\n setResult({ success: true, error: undefined });\n } else {\n setResult({ success: false, error: retryResult.error });\n }\n\n setTimeout(() => setResult(null), 3000);\n } catch (error) {\n console.error(\"Undo and retry error:\", error);\n setResult({ success: false, error: String(error) });\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleDone = () => {\n // Clear session before reload\n if (ENABLE_SESSION_PERSISTENCE && selectedSource) {\n AIEditorStorage.deleteSession(\n selectedSource.filePath,\n selectedSource.componentName\n );\n }\n // Close modal and reload page to see all changes\n window.location.reload();\n };\n\n const c = {\n bg: isDark ? \"#0d0d14\" : \"#fff\",\n bgAlt: isDark ? \"#16162a\" : \"#f5f5f5\",\n text: isDark ? \"#e4e4e7\" : \"#18181b\",\n muted: isDark ? \"#71717a\" : \"#a1a1aa\",\n accent: \"#818cf8\",\n border: isDark ? \"#27273f\" : \"#e4e4e7\",\n success: \"#34d399\",\n error: \"#f87171\",\n };\n\n const elCtx = selectedSource?.elementContext;\n\n return (\n <div\n className=\"ai-editor-ui\"\n style={{ fontFamily: \"system-ui, sans-serif\" }}\n >\n {/* Highlight */}\n {hoveredRect && !selectedSource && (\n <div\n style={{\n position: \"fixed\",\n left: hoveredRect.left - 2,\n top: hoveredRect.top - 2,\n width: hoveredRect.width + 4,\n height: hoveredRect.height + 4,\n border: `2px solid ${c.accent}`,\n borderRadius: 6,\n background: `${c.accent}15`,\n pointerEvents: \"none\",\n zIndex: 99998,\n }}\n />\n )}\n\n {/* Tooltip */}\n {hoveredSource && !selectedSource && !isResolvingSource && (\n <div\n style={{\n position: \"fixed\",\n left: Math.min(mousePos.x + 14, window.innerWidth - 340),\n top: mousePos.y + 14,\n background: c.bg,\n color: c.text,\n border: `1px solid ${c.border}`,\n borderRadius: 10,\n padding: \"12px 16px\",\n fontSize: 12,\n fontFamily: \"ui-monospace, monospace\",\n zIndex: 99999,\n boxShadow: `0 8px 30px rgba(0,0,0,${isDark ? 0.5 : 0.15})`,\n maxWidth: 320,\n pointerEvents: \"none\",\n }}\n >\n <div\n style={{\n fontWeight: 700,\n color: c.accent,\n marginBottom: 4,\n fontSize: 14,\n }}\n >\n &lt;{hoveredSource.componentName} /&gt;\n </div>\n <div style={{ color: c.muted, fontSize: 11 }}>\n {hoveredSource.filePath}:{hoveredSource.lineNumber}\n </div>\n {hoveredSource.elementContext?.textContent && (\n <div\n style={{\n color: c.muted,\n fontSize: 10,\n marginTop: 4,\n fontStyle: \"italic\",\n }}\n >\n \"{hoveredSource.elementContext.textContent}\"\n </div>\n )}\n </div>\n )}\n\n {/* Stale File Warning Modal */}\n {ENABLE_SESSION_PERSISTENCE && showStaleWarning && staleSession && (\n <div\n style={{\n position: \"fixed\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: \"rgba(0,0,0,0.7)\",\n zIndex: 100001,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n <div\n style={{\n background: c.bg,\n color: c.text,\n borderRadius: 16,\n padding: 32,\n maxWidth: 500,\n border: `1px solid ${c.border}`,\n boxShadow: `0 24px 80px rgba(0,0,0,0.8)`,\n }}\n >\n <div style={{ fontSize: 24, marginBottom: 16 }}>\n ⚠️ File Modified Externally\n </div>\n <p style={{ marginBottom: 12, color: c.muted }}>\n The file has been modified since your last edit session.\n </p>\n <div\n style={{\n background: c.bgAlt,\n padding: 12,\n borderRadius: 8,\n marginBottom: 20,\n fontFamily: \"monospace\",\n fontSize: 12,\n }}\n >\n <div>\n <strong>Component:</strong>{\" \"}\n {staleSession.sourceLocation.componentName}\n </div>\n <div>\n <strong>File:</strong> {staleSession.sourceLocation.filePath}\n </div>\n <div>\n <strong>Last edit:</strong>{\" \"}\n {new Date(staleSession.lastModified).toLocaleString()}\n </div>\n <div>\n <strong>Edits:</strong> {staleSession.editHistory.length}\n </div>\n </div>\n <p style={{ marginBottom: 20, fontSize: 14 }}>\n Continuing may cause conflicts. You can discard this session or\n continue anyway.\n </p>\n <div style={{ display: \"flex\", gap: 12 }}>\n <button\n onClick={() => {\n AIEditorStorage.deleteSession(\n staleSession.sourceLocation.filePath,\n staleSession.sourceLocation.componentName\n );\n setShowStaleWarning(false);\n setStaleSession(null);\n setHasActiveSession(false);\n }}\n style={{\n flex: 1,\n padding: \"12px 20px\",\n borderRadius: 10,\n border: `1px solid ${c.border}`,\n background: \"transparent\",\n color: c.text,\n cursor: \"pointer\",\n }}\n >\n Discard Session\n </button>\n <button\n onClick={() => {\n restoreSession(staleSession);\n setShowStaleWarning(false);\n }}\n style={{\n flex: 1,\n padding: \"12px 20px\",\n borderRadius: 10,\n border: \"none\",\n background: \"#f59e0b\",\n color: \"#fff\",\n fontWeight: 600,\n cursor: \"pointer\",\n }}\n >\n Continue Anyway\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Modal */}\n {selectedSource && (\n <div\n style={{\n position: \"fixed\",\n bottom: 20,\n right: 20,\n background: c.bg,\n color: c.text,\n borderRadius: 16,\n padding: 24,\n width: 560,\n maxWidth: \"calc(100vw - 40px)\",\n maxHeight: \"calc(100vh - 40px)\",\n overflowY: \"auto\",\n overflowX: \"hidden\",\n zIndex: 100000,\n boxShadow: `0 24px 80px rgba(0,0,0,${isDark ? 0.6 : 0.25})`,\n border: `1px solid ${c.border}`,\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n marginBottom: 20,\n }}\n >\n <div>\n <div\n style={{\n fontSize: 11,\n textTransform: \"uppercase\",\n letterSpacing: 1,\n color: c.muted,\n }}\n >\n Editing\n </div>\n <div style={{ fontSize: 20, fontWeight: 700, color: c.accent }}>\n &lt;{parsedComponentName || selectedSource.componentName} /&gt;\n </div>\n <div\n style={{\n fontSize: 12,\n color: c.muted,\n fontFamily: \"monospace\",\n marginTop: 4,\n }}\n >\n <a\n href={\n absolutePath\n ? `cursor://file/${absolutePath}:${selectedSource.lineNumber}`\n : `cursor://file/${selectedSource.filePath}:${selectedSource.lineNumber}`\n }\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n const path = absolutePath || selectedSource.filePath;\n const cursorPath = path.startsWith(\"/\") ? path : `/${path}`;\n window.location.href = `cursor://file${cursorPath}:${selectedSource.lineNumber}`;\n }}\n style={{\n color: c.accent,\n textDecoration: \"none\",\n cursor: \"pointer\",\n borderBottom: `1px solid ${c.accent}40`,\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.borderBottomColor = c.accent;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.borderBottomColor = `${c.accent}40`;\n }}\n >\n {selectedSource.filePath}:{selectedSource.lineNumber}\n </a>\n </div>\n {elCtx?.textContent && (\n <div\n style={{\n fontSize: 11,\n color: c.muted,\n marginTop: 4,\n fontStyle: \"italic\",\n }}\n >\n Element text: \"{elCtx.textContent}\"\n </div>\n )}\n </div>\n <button\n onClick={() => setSelectedSource(null)}\n style={{\n width: 36,\n height: 36,\n borderRadius: 10,\n border: \"none\",\n background: c.bgAlt,\n color: c.muted,\n fontSize: 20,\n cursor: \"pointer\",\n }}\n >\n ×\n </button>\n </div>\n\n {code && (\n <div style={{ marginBottom: 20 }}>\n <div\n style={{\n fontSize: 11,\n fontWeight: 600,\n marginBottom: 8,\n color: c.muted,\n textTransform: \"uppercase\",\n }}\n >\n Source Preview\n </div>\n <SyntaxHighlighter\n language=\"tsx\"\n style={isDark ? vscDarkPlus : vs}\n showLineNumbers={true}\n startingLineNumber={codeLineStart}\n customStyle={{\n background: c.bgAlt,\n borderRadius: 10,\n fontSize: 14,\n margin: 0,\n maxHeight: 180,\n overflowX: \"auto\",\n border: `1px solid ${c.border}`,\n }}\n lineNumberStyle={{\n minWidth: \"2.5em\",\n paddingRight: \"1em\",\n color: c.muted,\n textAlign: \"right\",\n userSelect: \"none\",\n }}\n wrapLines={true}\n lineProps={(lineNumber) => {\n const isHighlighted =\n targetStartLine !== null &&\n targetEndLine !== null &&\n lineNumber >= targetStartLine &&\n lineNumber <= targetEndLine;\n return {\n style: {\n backgroundColor: isHighlighted\n ? isDark\n ? \"rgba(102, 126, 234, 0.15)\"\n : \"rgba(147, 197, 253, 0.3)\"\n : \"transparent\",\n },\n };\n }}\n >\n {code}\n </SyntaxHighlighter>\n </div>\n )}\n\n {editHistory.length > 0 && (\n <div style={{ marginBottom: 20 }}>\n <div\n style={{\n fontSize: 11,\n fontWeight: 600,\n marginBottom: 8,\n color: c.muted,\n textTransform: \"uppercase\",\n }}\n >\n Edit History ({editHistory.length})\n </div>\n <div\n style={{\n background: c.bgAlt,\n borderRadius: 10,\n border: `1px solid ${c.border}`,\n maxHeight: 200,\n overflow: \"auto\",\n }}\n >\n {editHistory.map((item, idx) => {\n const isLastEdit = idx === editHistory.length - 1;\n const hasSnapshot = item.success && item.fileSnapshot;\n\n return (\n <div\n key={idx}\n style={{\n padding: \"10px 14px\",\n borderBottom:\n idx < editHistory.length - 1\n ? `1px solid ${c.border}`\n : \"none\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"flex-start\",\n gap: 8,\n }}\n >\n <div style={{ flex: 1 }}>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n marginBottom: 4,\n }}\n >\n <span\n style={{\n color: item.success ? c.success : c.error,\n fontSize: 16,\n }}\n >\n {item.success ? \"✓\" : \"✗\"}\n </span>\n <span\n style={{\n fontSize: 11,\n color: c.muted,\n }}\n >\n Edit {idx + 1}\n </span>\n </div>\n <div\n style={{\n fontSize: 13,\n color: c.text,\n marginLeft: 24,\n }}\n >\n {item.suggestion}\n </div>\n {item.error && (\n <div\n style={{\n fontSize: 11,\n color: c.error,\n marginLeft: 24,\n marginTop: 4,\n }}\n >\n {item.error}\n </div>\n )}\n </div>\n <div style={{ display: \"flex\", gap: 6, flexWrap: \"wrap\" }}>\n {isLastEdit && hasSnapshot && (\n <>\n <button\n onClick={handleUndo}\n disabled={isLoading}\n style={{\n padding: \"4px 10px\",\n fontSize: 11,\n borderRadius: 6,\n border: \"none\",\n background: isLoading ? c.muted : \"#f59e0b\",\n color: \"#fff\",\n fontWeight: 600,\n cursor: isLoading ? \"wait\" : \"pointer\",\n whiteSpace: \"nowrap\",\n }}\n title=\"Undo this edit\"\n onMouseEnter={(e) => {\n if (!isLoading)\n e.currentTarget.style.background = \"#d97706\";\n }}\n onMouseLeave={(e) => {\n if (!isLoading)\n e.currentTarget.style.background = \"#f59e0b\";\n }}\n >\n ↶ Undo\n </button>\n <button\n onClick={handleUndoAndRetry}\n disabled={isLoading}\n style={{\n padding: \"4px 10px\",\n fontSize: 11,\n borderRadius: 6,\n border: \"none\",\n background: isLoading ? c.muted : \"#8b5cf6\",\n color: \"#fff\",\n fontWeight: 600,\n cursor: isLoading ? \"wait\" : \"pointer\",\n whiteSpace: \"nowrap\",\n }}\n title=\"Undo and retry with AI\"\n onMouseEnter={(e) => {\n if (!isLoading)\n e.currentTarget.style.background = \"#7c3aed\";\n }}\n onMouseLeave={(e) => {\n if (!isLoading)\n e.currentTarget.style.background = \"#8b5cf6\";\n }}\n >\n ↶↻ Undo & Retry\n </button>\n </>\n )}\n <button\n onClick={() => handleRetry(idx)}\n disabled={isLoading}\n style={{\n padding: \"4px 10px\",\n fontSize: 11,\n borderRadius: 6,\n border: \"none\",\n background: isLoading ? c.muted : c.accent,\n color: \"#fff\",\n fontWeight: 600,\n cursor: isLoading ? \"wait\" : \"pointer\",\n whiteSpace: \"nowrap\",\n }}\n title=\"Retry this edit\"\n onMouseEnter={(e) => {\n if (!isLoading)\n e.currentTarget.style.background = \"#6366f1\";\n }}\n onMouseLeave={(e) => {\n if (!isLoading)\n e.currentTarget.style.background = c.accent;\n }}\n >\n ↻ Retry\n </button>\n </div>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n )}\n\n <div style={{ marginBottom: 20 }}>\n <div\n style={{\n fontSize: 11,\n fontWeight: 600,\n marginBottom: 8,\n color: c.muted,\n textTransform: \"uppercase\",\n }}\n >\n Describe Changes\n </div>\n <textarea\n value={suggestion}\n onChange={(e) => setSuggestion(e.target.value)}\n placeholder={`e.g., Make this ${\n elCtx?.tagName || \"element\"\n } blue with rounded corners...`}\n autoFocus\n style={{\n width: \"100%\",\n height: 100,\n padding: 14,\n borderRadius: 10,\n border: `1px solid ${c.border}`,\n background: c.bgAlt,\n color: c.text,\n fontSize: 14,\n resize: \"vertical\",\n fontFamily: \"inherit\",\n boxSizing: \"border-box\",\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n handleSubmit();\n }\n }}\n />\n </div>\n\n {result && (\n <div\n style={{\n marginBottom: 20,\n padding: 14,\n borderRadius: 10,\n background: result.success ? `${c.success}15` : `${c.error}15`,\n color: result.success ? c.success : c.error,\n fontWeight: 500,\n }}\n >\n {result.success ? \"✓ Applied!\" : `✗ ${result.error}`}\n </div>\n )}\n\n <div style={{ display: \"flex\", gap: 12, flexWrap: \"wrap\" }}>\n <button\n onClick={() => setSelectedSource(null)}\n style={{\n flex: \"1 1 auto\",\n padding: \"12px 20px\",\n borderRadius: 10,\n border: `1px solid ${c.border}`,\n background: \"transparent\",\n color: c.text,\n cursor: \"pointer\",\n }}\n >\n Cancel\n </button>\n\n {/* Clear Session Button */}\n {ENABLE_SESSION_PERSISTENCE && (\n <button\n onClick={handleClearSession}\n style={{\n flex: \"0 0 auto\",\n padding: \"12px 20px\",\n borderRadius: 10,\n border: `1px solid ${c.error}`,\n background: \"transparent\",\n color: c.error,\n cursor: \"pointer\",\n fontSize: 12,\n }}\n title=\"Clear this session and start fresh\"\n >\n Clear Session\n </button>\n )}\n\n {editHistory.length > 0 && (\n <button\n onClick={handleDone}\n style={{\n flex: \"1 1 auto\",\n padding: \"12px 20px\",\n borderRadius: 10,\n border: `1px solid ${c.success}`,\n background: \"transparent\",\n color: c.success,\n fontWeight: 600,\n cursor: \"pointer\",\n }}\n >\n Finish & Reload\n </button>\n )}\n <button\n onClick={handleSubmit}\n disabled={isLoading || !suggestion.trim()}\n style={{\n flex: \"2 1 auto\",\n padding: \"12px 20px\",\n borderRadius: 10,\n border: \"none\",\n background: isLoading ? c.muted : c.accent,\n color: \"#fff\",\n fontWeight: 600,\n cursor: isLoading ? \"wait\" : \"pointer\",\n opacity: !suggestion.trim() ? 0.5 : 1,\n }}\n >\n {isLoading ? \"Applying...\" : \"Apply Changes ⌘↵\"}\n </button>\n </div>\n </div>\n )}\n\n {/* Badge */}\n {!selectedSource && (\n <div\n style={{\n position: \"fixed\",\n bottom: 20,\n right: 20,\n background: c.bg,\n color: c.success,\n padding: \"10px 16px\",\n borderRadius: 20,\n fontSize: 13,\n fontWeight: 600,\n zIndex: 99997,\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n border: `1px solid ${c.border}`,\n boxShadow: `0 4px 20px rgba(0,0,0,${isDark ? 0.4 : 0.1})`,\n }}\n >\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: c.success,\n }}\n />\n AI Editor\n <span style={{ color: c.muted, fontSize: 11 }}>⌘⇧E</span>\n\n {ENABLE_SESSION_PERSISTENCE && hasActiveSession && (\n <>\n <span style={{ color: c.muted }}>|</span>\n <span style={{ color: \"#f59e0b\", fontSize: 11 }}>📝 Session</span>\n <button\n onClick={handleClearSession}\n style={{\n background: \"none\",\n border: \"none\",\n color: c.muted,\n cursor: \"pointer\",\n fontSize: 11,\n }}\n title=\"Clear active session\"\n >\n 🗑️\n </button>\n </>\n )}\n\n <button\n onClick={() => setEnabled(false)}\n style={{\n background: \"none\",\n border: \"none\",\n color: c.muted,\n cursor: \"pointer\",\n }}\n >\n ×\n </button>\n </div>\n )}\n </div>\n );\n}\n"],"names":["resolved","_a","result","SyntaxHighlighter"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-BFa7H-uO.js","sources":["../src/server/utils/file-system.ts","../src/server/utils/ast.ts","../src/server/handlers/edit.ts","../src/server/utils/source-map.ts","../src/server/handlers/read.ts","../src/server/handlers/undo.ts","../src/server/handlers/resolve.ts","../src/server/handlers/absolute-path.ts","../src/server/handlers/validate-session.ts","../src/server/handlers/index.ts"],"sourcesContent":["// =============================================================================\n// FILE: lib/ai-editor-utils.ts\n// Shared utilities for AI editor API routes\n// =============================================================================\n\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport { NextResponse } from \"next/server\";\n\n/**\n * Validate that we're in development mode\n * Returns error response if not in dev mode, null otherwise\n */\nexport function validateDevMode(): NextResponse | null {\n if (process.env.NODE_ENV !== \"development\") {\n return NextResponse.json(\n { success: false, error: \"Development mode only\" },\n { status: 403 },\n );\n }\n return null;\n}\n\n/**\n * Normalize file path by removing webpack/turbopack prefixes\n */\nexport function normalizePath(filePath: string): string {\n return filePath\n .replace(/^webpack-internal:\\/\\/\\/\\([^)]+\\)\\/\\.?/, \"\")\n .replace(/^webpack:\\/\\/[^/]*\\//, \"\")\n .replace(/^\\.\\//, \"\")\n .replace(/\\?.*$/, \"\");\n}\n\n/**\n * Resolve a file path to an absolute path within the project\n * Returns null if file doesn't exist or is outside project root\n */\nexport async function resolveFilePath(\n projectRoot: string,\n normalizedPath: string,\n): Promise<string | null> {\n const candidates = [\n path.resolve(projectRoot, normalizedPath),\n path.resolve(projectRoot, \"src\", normalizedPath),\n path.resolve(projectRoot, \"app\", normalizedPath),\n ];\n\n for (const candidate of candidates) {\n // Security: ensure path is within project root\n if (!candidate.startsWith(projectRoot)) continue;\n\n try {\n await fs.access(candidate);\n return candidate;\n } catch {\n // File doesn't exist, try next candidate\n }\n }\n\n return null;\n}\n\n/**\n * Validate that a file path is within the project root (security check)\n */\nexport function isPathSecure(\n absolutePath: string,\n projectRoot: string,\n): boolean {\n return absolutePath.startsWith(projectRoot);\n}\n\n/**\n * Check if a file exists\n */\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n","// =============================================================================\n// FILE: lib/ai-editor-ast.ts\n// Shared AST parsing and element matching utilities for AI editor\n// =============================================================================\n\nimport * as parser from \"@babel/parser\";\nimport traverse from \"@babel/traverse\";\nimport type { NodePath } from \"@babel/traverse\";\nimport * as t from \"@babel/types\";\nimport type { ElementContext } from \"../../shared/types\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\nexport interface ElementMatch {\n node: t.JSXElement | t.JSXFragment;\n startLine: number;\n endLine: number;\n score: number;\n}\n\nexport interface TargetElementResult {\n startLine: number;\n endLine: number;\n componentStart: number;\n componentEnd: number;\n}\n\n// =============================================================================\n// PARSING\n// =============================================================================\n\n/**\n * Parse a file with Babel (TypeScript + JSX)\n */\nexport function parseFile(content: string): t.File | null {\n try {\n return parser.parse(content, {\n sourceType: \"module\",\n plugins: [\n \"jsx\",\n \"typescript\",\n \"decorators-legacy\",\n \"classProperties\",\n \"optionalChaining\",\n \"nullishCoalescingOperator\",\n ],\n });\n } catch (e) {\n console.error(\"Parse error:\", e);\n return null;\n }\n}\n\n// =============================================================================\n// ELEMENT FINDING\n// =============================================================================\n\n/**\n * Find the target element in the AST\n */\nexport function findTargetElement(\n ast: t.File,\n fileContent: string,\n options: {\n componentName: string;\n lineNumber: number;\n elementContext?: ElementContext;\n },\n): TargetElementResult | null {\n const { componentName, lineNumber, elementContext } = options;\n const matches: ElementMatch[] = [];\n\n // First, find the component function/class\n let componentNode: t.Node | null = null;\n let componentStart = 0;\n let componentEnd = Infinity;\n let fallbackExportDefault: { node: t.Node; start: number; end: number } | null =\n null;\n\n traverse(ast, {\n FunctionDeclaration(path: NodePath<t.FunctionDeclaration>) {\n if (path.node.id?.name === componentName) {\n componentNode = path.node;\n componentStart = path.node.loc?.start.line || 0;\n componentEnd = path.node.loc?.end.line || Infinity;\n }\n },\n VariableDeclarator(path: NodePath<t.VariableDeclarator>) {\n if (\n t.isIdentifier(path.node.id) &&\n path.node.id.name === componentName\n ) {\n componentNode = path.node;\n const parent = path.parentPath.parent;\n componentStart = parent?.loc?.start.line || 0;\n componentEnd = parent?.loc?.end.line || Infinity;\n }\n },\n ExportDefaultDeclaration(path: NodePath<t.ExportDefaultDeclaration>) {\n if (t.isFunctionDeclaration(path.node.declaration)) {\n const funcName = path.node.declaration.id?.name;\n if (funcName === componentName || !funcName) {\n componentNode = path.node;\n componentStart = path.node.loc?.start.line || 0;\n componentEnd = path.node.loc?.end.line || Infinity;\n } else if (!componentNode) {\n // Store as fallback if we don't find an exact match\n fallbackExportDefault = {\n node: path.node,\n start: path.node.loc?.start.line || 0,\n end: path.node.loc?.end.line || Infinity,\n };\n }\n }\n },\n });\n\n // If we didn't find the component by name, use the export default as fallback\n if (!componentNode && fallbackExportDefault !== null) {\n const fallback = fallbackExportDefault as { node: t.Node; start: number; end: number };\n console.log(\n `⚠️ Component \"${componentName}\" not found, using export default function as fallback`,\n );\n componentNode = fallback.node;\n componentStart = fallback.start;\n componentEnd = fallback.end;\n }\n\n // Find JSX elements within the component\n const allElementsByTag: Map<string, ElementMatch[]> = new Map();\n traverse(ast, {\n JSXElement(path: NodePath<t.JSXElement>) {\n const loc = path.node.loc;\n if (!loc) return;\n\n const startLine = loc.start.line;\n const endLine = loc.end.line;\n\n // Must be within component bounds\n if (startLine < componentStart || endLine > componentEnd) return;\n\n // Track ALL elements by tag name for nthOfType matching\n const opening = path.node.openingElement;\n if (t.isJSXIdentifier(opening.name)) {\n const tagName = opening.name.name;\n if (!allElementsByTag.has(tagName)) {\n allElementsByTag.set(tagName, []);\n }\n allElementsByTag\n .get(tagName)!\n .push({ node: path.node, startLine, endLine, score: 0 });\n }\n\n // If we have element context, match against it\n if (elementContext) {\n const score = scoreElementMatch(path.node, elementContext, fileContent);\n if (score > 0) {\n matches.push({ node: path.node, startLine, endLine, score });\n }\n } else if (Math.abs(startLine - lineNumber) <= 5) {\n // Fallback: find element near the hint line\n matches.push({\n node: path.node,\n startLine,\n endLine,\n score: 100 - Math.abs(startLine - lineNumber),\n });\n }\n },\n });\n\n if (matches.length === 0) {\n // Fallback: return component bounds\n if (componentNode && componentStart > 0) {\n return {\n startLine: componentStart,\n endLine: componentEnd,\n componentStart,\n componentEnd,\n };\n }\n return null;\n }\n\n // Handle nthOfType - use ALL elements of that tag, not just scored matches\n if (elementContext?.nthOfType && elementContext.tagName) {\n const allOfTag = allElementsByTag.get(elementContext.tagName);\n if (allOfTag && allOfTag.length >= elementContext.nthOfType) {\n const target = allOfTag[elementContext.nthOfType - 1];\n console.log(\n ` Using nthOfType=${elementContext.nthOfType}: found ${allOfTag.length} <${elementContext.tagName}> elements`,\n );\n return {\n startLine: target.startLine,\n endLine: target.endLine,\n componentStart,\n componentEnd,\n };\n } else {\n console.log(\n ` nthOfType=${elementContext.nthOfType} but only found ${allOfTag?.length || 0} <${elementContext.tagName}> elements`,\n );\n }\n }\n\n // Return highest scoring match\n matches.sort((a, b) => b.score - a.score);\n const best = matches[0];\n return {\n startLine: best.startLine,\n endLine: best.endLine,\n componentStart,\n componentEnd,\n };\n}\n\n// =============================================================================\n// ELEMENT MATCHING\n// =============================================================================\n\n/**\n * Score an element match against the provided context\n */\nexport function scoreElementMatch(\n node: t.JSXElement,\n context: ElementContext,\n fileContent: string,\n): number {\n let score = 0;\n const opening = node.openingElement;\n\n // Check tag name\n if (t.isJSXIdentifier(opening.name)) {\n if (opening.name.name === context.tagName) {\n score += 50;\n } else {\n return 0; // Tag must match\n }\n } else if (t.isJSXMemberExpression(opening.name)) {\n // Handle things like Motion.div\n const fullName = getJSXMemberName(opening.name);\n if (\n fullName === context.tagName ||\n fullName.endsWith(`.${context.tagName}`)\n ) {\n score += 50;\n } else {\n return 0;\n }\n }\n\n // Check className\n if (context.className) {\n const classAttr = opening.attributes.find(\n (attr: t.JSXAttribute | t.JSXSpreadAttribute) =>\n t.isJSXAttribute(attr) &&\n t.isJSXIdentifier(attr.name) &&\n attr.name.name === \"className\",\n );\n if (classAttr && t.isJSXAttribute(classAttr)) {\n const classValue = getAttributeValue(classAttr);\n if (\n classValue &&\n context.className.split(/\\s+/).some((c) => classValue.includes(c))\n ) {\n score += 20;\n }\n }\n }\n\n // Check text content\n if (context.textContent && node.loc) {\n const elementCode = fileContent\n .split(\"\\n\")\n .slice(node.loc.start.line - 1, node.loc.end.line)\n .join(\"\\n\");\n const normalizedContent = context.textContent.toLowerCase().trim();\n const normalizedElement = elementCode.toLowerCase();\n if (normalizedElement.includes(normalizedContent)) {\n score += 30;\n }\n }\n\n // Check props\n if (context.props) {\n for (const [key, value] of Object.entries(context.props)) {\n if (key.startsWith(\"_\")) continue;\n const attr = opening.attributes.find(\n (a: t.JSXAttribute | t.JSXSpreadAttribute) =>\n t.isJSXAttribute(a) &&\n t.isJSXIdentifier(a.name) &&\n a.name.name === key,\n );\n if (attr) {\n score += 5;\n if (typeof value === \"string\" && t.isJSXAttribute(attr)) {\n const attrValue = getAttributeValue(attr);\n if (attrValue === value) score += 10;\n }\n }\n }\n }\n\n return score;\n}\n\n/**\n * Get the full name of a JSX member expression (e.g., \"Motion.div\")\n */\nexport function getJSXMemberName(node: t.JSXMemberExpression): string {\n if (t.isJSXIdentifier(node.object)) {\n return `${node.object.name}.${node.property.name}`;\n }\n if (t.isJSXMemberExpression(node.object)) {\n return `${getJSXMemberName(node.object)}.${node.property.name}`;\n }\n return node.property.name;\n}\n\n/**\n * Get the value of a JSX attribute\n */\nexport function getAttributeValue(attr: t.JSXAttribute): string | null {\n if (!attr.value) return null;\n if (t.isStringLiteral(attr.value)) return attr.value.value;\n if (\n t.isJSXExpressionContainer(attr.value) &&\n t.isStringLiteral(attr.value.expression)\n ) {\n return attr.value.expression.value;\n }\n return null;\n}\n","// =============================================================================\n// FILE: app/api/ai-editor/edit/route.ts\n// Robust AI code editor using Babel AST parsing\n// =============================================================================\n\nimport { NextRequest, NextResponse } from \"next/server\";\nimport fs from \"fs/promises\";\nimport * as parser from \"@babel/parser\";\nimport { ChatAnthropic } from \"@langchain/anthropic\";\nimport { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\nimport {\n validateDevMode,\n normalizePath,\n resolveFilePath,\n} from \"../utils/file-system\";\nimport {\n parseFile,\n findTargetElement,\n} from \"../utils/ast\";\nimport type { ElementContext } from \"../../shared/types\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface EditHistoryItem {\n suggestion: string;\n success: boolean;\n}\n\ninterface EditRequest {\n filePath: string;\n lineNumber: number;\n componentName: string;\n suggestion: string;\n elementContext?: ElementContext;\n debugStack?: string;\n editHistory?: EditHistoryItem[];\n}\n\n// =============================================================================\n// MAIN HANDLER\n// =============================================================================\n\nexport async function handleEdit(req: NextRequest): Promise<NextResponse> {\n const devModeError = validateDevMode();\n if (devModeError) return devModeError;\n\n try {\n const body: EditRequest = await req.json();\n const {\n filePath,\n lineNumber,\n componentName,\n suggestion,\n elementContext,\n editHistory,\n } = body;\n\n const projectRoot = process.cwd();\n const normalizedPath = normalizePath(filePath);\n const absolutePath = await resolveFilePath(projectRoot, normalizedPath);\n\n if (!absolutePath) {\n return NextResponse.json(\n { success: false, error: `File not found: ${normalizedPath}` },\n { status: 404 },\n );\n }\n\n const fileContent = await fs.readFile(absolutePath, \"utf-8\");\n\n console.log(`[/edit] componentName=\"${componentName}\", filePath=\"${filePath}\"`);\n\n // Parse the file with Babel\n const ast = parseFile(fileContent);\n if (!ast) {\n return NextResponse.json(\n { success: false, error: \"Failed to parse file\" },\n { status: 400 },\n );\n }\n\n // Find the target element\n const target = findTargetElement(ast, fileContent, {\n componentName,\n lineNumber,\n elementContext,\n });\n\n if (!target) {\n return NextResponse.json(\n { success: false, error: \"Could not locate target element\" },\n { status: 400 },\n );\n }\n\n console.log(\n `📍 Found element <${elementContext?.tagName || \"component\"}> at lines ${\n target.startLine\n }-${target.endLine} (component: ${target.componentStart}-${target.componentEnd})`,\n );\n console.log(\n ` Element context: tagName=${elementContext?.tagName}, nthOfType=${elementContext?.nthOfType}, textContent=\"${elementContext?.textContent}\"`,\n );\n\n // Extract the code to modify\n const lines = fileContent.split(\"\\n\");\n\n // Log the actual found element code for debugging\n const foundElementCode = lines\n .slice(target.startLine - 1, Math.min(target.startLine + 2, target.endLine))\n .join(\"\\n\");\n console.log(` Found element preview:\\n${foundElementCode}`);\n const targetCode = lines\n .slice(target.startLine - 1, target.endLine)\n .join(\"\\n\");\n const baseIndentation =\n lines[target.startLine - 1].match(/^(\\s*)/)?.[1] || \"\";\n\n // Extract the full component code with line markers for the clicked element\n // Handle invalid component bounds\n if (target.componentStart <= 0 || target.componentEnd === Infinity) {\n console.error(\"❌ Invalid component bounds detected\");\n return NextResponse.json({\n success: false,\n error: `Could not determine component bounds. Component: ${target.componentStart}-${target.componentEnd}`,\n });\n }\n\n const componentLines = lines.slice(\n target.componentStart - 1,\n target.componentEnd,\n );\n\n // Add line number annotations to help AI identify target\n const annotatedLines = componentLines.map((line, idx) => {\n const lineNum = target.componentStart + idx;\n const isTargetStart = lineNum === target.startLine;\n const isTargetEnd = lineNum === target.endLine;\n const isWithinTarget = lineNum >= target.startLine && lineNum <= target.endLine;\n\n let annotation = \"\";\n if (isTargetStart && isTargetEnd) {\n annotation = \" // ← CLICKED ELEMENT (single line)\";\n } else if (isTargetStart) {\n annotation = \" // ← CLICKED ELEMENT STARTS\";\n } else if (isTargetEnd) {\n annotation = \" // ← CLICKED ELEMENT ENDS\";\n } else if (isWithinTarget) {\n annotation = \" // ← (clicked element)\";\n }\n\n return line + annotation;\n });\n\n const fullComponentCode = annotatedLines.join(\"\\n\");\n\n // Generate the edit with AI\n const newCode = await generateEdit({\n targetCode,\n fullComponentCode,\n suggestion,\n elementContext,\n baseIndentation,\n targetLine: target.startLine,\n targetEndLine: target.endLine,\n componentStart: target.componentStart,\n componentEnd: target.componentEnd,\n editHistory: editHistory || [],\n });\n\n if (!newCode) {\n return NextResponse.json({\n success: false,\n error: \"AI failed to generate valid edit\",\n });\n }\n\n // Check if AI returned full component or just target element\n // The AI might return both, so look for the marker anywhere in the response\n console.log(\"Raw AI response length:\", newCode.length);\n console.log(\"Looking for // FULL_COMPONENT marker...\");\n\n const fullComponentMatch = newCode.match(/\\/\\/ FULL_COMPONENT\\s*\\n([\\s\\S]+)/);\n let codeToApply = newCode;\n let startLineToReplace = target.startLine;\n let endLineToReplace = target.endLine;\n\n if (fullComponentMatch) {\n console.log(\"Found // FULL_COMPONENT marker, extracting full component code\");\n // Extract just the full component code after the marker\n codeToApply = fullComponentMatch[1].trim();\n startLineToReplace = target.componentStart;\n endLineToReplace = target.componentEnd;\n console.log(\n `🔄 AI returned full component modification (lines ${startLineToReplace}-${endLineToReplace})`,\n );\n console.log(\"Extracted component code length:\", codeToApply.length);\n console.log(\"Extracted component code (first 300 chars):\", codeToApply.substring(0, 300));\n } else {\n console.log(\"No // FULL_COMPONENT marker found, treating as target element modification\");\n console.log(\n `🔄 AI returned target element modification (lines ${startLineToReplace}-${endLineToReplace})`,\n );\n }\n\n console.log(\"Code to apply (first 200 chars):\", codeToApply.substring(0, 200));\n\n // Validate the generated code parses correctly\n if (!validateGeneratedCode(codeToApply, targetCode, fileContent)) {\n console.error(\"❌ Generated code failed validation\");\n console.error(\"=== Generated code START ===\");\n console.error(codeToApply);\n console.error(\"=== Generated code END ===\");\n console.error(`Length: ${codeToApply.length} chars, ${codeToApply.split('\\n').length} lines`);\n return NextResponse.json({\n success: false,\n error: \"Generated code is invalid - check server logs for details\",\n });\n }\n\n // Apply the edit\n const newLines = [...lines];\n newLines.splice(\n startLineToReplace - 1,\n endLineToReplace - startLineToReplace + 1,\n ...codeToApply.split(\"\\n\"),\n );\n\n await fs.writeFile(absolutePath, newLines.join(\"\\n\"), \"utf-8\");\n\n console.log(`✅ Updated ${normalizedPath}`);\n return NextResponse.json({\n success: true,\n fileSnapshot: fileContent, // Original file content for undo\n generatedCode: codeToApply, // AI-generated code\n modifiedLines: {\n start: startLineToReplace,\n end: endLineToReplace,\n },\n });\n } catch (error) {\n console.error(\"AI Editor error:\", error);\n return NextResponse.json(\n { success: false, error: String(error) },\n { status: 500 },\n );\n }\n}\n\n// =============================================================================\n// AI EDIT GENERATION\n// =============================================================================\n\nasync function generateEdit(options: {\n targetCode: string;\n fullComponentCode: string;\n suggestion: string;\n elementContext?: ElementContext;\n baseIndentation: string;\n targetLine: number;\n targetEndLine: number;\n componentStart: number;\n componentEnd: number;\n editHistory: EditHistoryItem[];\n}): Promise<string | null> {\n const {\n targetCode,\n fullComponentCode,\n suggestion,\n elementContext,\n baseIndentation,\n targetLine,\n targetEndLine,\n componentStart,\n componentEnd,\n editHistory,\n } = options;\n\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (!apiKey) throw new Error(\"ANTHROPIC_API_KEY not set\");\n\n const model = new ChatAnthropic({\n apiKey,\n modelName: \"claude-sonnet-4-5-20250929\",\n maxTokens: 4096,\n temperature: 0,\n });\n\n const systemPrompt = `You are a precise code editor for React/JSX components.\n\nWHAT YOU'LL SEE:\n- Full component code with line annotations\n- The clicked element is marked with \"// ← CLICKED ELEMENT STARTS\" and \"// ← CLICKED ELEMENT ENDS\"\n- Lines within the element have \"// ← (clicked element)\"\n- These are just annotations to help you - they are NOT part of the actual code\n\nYOUR TASK:\nModify ONLY the marked element (unless the request requires changing its parent/wrapper).\n\nOUTPUT:\n- Just the modified element code (WITHOUT the annotation comments)\n- OR if broader changes needed: \"// FULL_COMPONENT\\\\n\" + complete modified component (WITHOUT annotation comments)\n\nRULES:\n- Output ONLY code, no explanations\n- No markdown fences\n- Do NOT include the \"// ← CLICKED ELEMENT\" annotation comments in your output\n- Preserve indentation\n- Make minimal changes\n- Do NOT modify unrelated elements`;\n\n let userPrompt = \"\";\n\n // If there's edit history, provide context about previous changes\n if (editHistory.length > 0) {\n userPrompt += \"Previous edits made to this element:\\n\";\n editHistory.forEach((item, idx) => {\n userPrompt += `${idx + 1}. ${item.suggestion} ${item.success ? \"(✓ applied)\" : \"(✗ failed)\"}\\n`;\n });\n userPrompt += \"\\n\";\n }\n\n // Show full component with annotations\n userPrompt += `Component (clicked element is annotated with \"// ← CLICKED ELEMENT\" comments):\n\n\\`\\`\\`jsx\n${fullComponentCode}\n\\`\\`\\`\n\nUser request: \"${suggestion}\"\n${editHistory.length > 0 ? \"\\n(Build upon previous changes)\" : \"\"}\n\nModify the annotated element to fulfill this request. Remember: do NOT include the annotation comments in your output.`;\n\n try {\n const response = await model.invoke([\n new SystemMessage(systemPrompt),\n new HumanMessage(userPrompt),\n ]);\n\n let code =\n typeof response.content === \"string\"\n ? response.content\n : String(response.content);\n\n // Clean up AI response\n code = cleanGeneratedCode(code, baseIndentation);\n\n return code || null;\n } catch (e) {\n console.error(\"AI generation error:\", e);\n return null;\n }\n}\n\nfunction cleanGeneratedCode(code: string, baseIndentation: string): string {\n // Check if this is a full component modification (preserve the marker)\n const isFullComponent = code.trim().startsWith(\"// FULL_COMPONENT\");\n let marker = \"\";\n if (isFullComponent) {\n marker = \"// FULL_COMPONENT\\n\";\n code = code.replace(/^\\/\\/ FULL_COMPONENT\\n?/, \"\");\n }\n\n // Remove markdown fences\n code = code\n .replace(/^```[\\w]*\\n?/gm, \"\")\n .replace(/\\n?```$/gm, \"\")\n .trim();\n\n // Remove common AI prefixes\n code = code\n .replace(/^(Here'?s?|Here is|Modified|Output|Result)[:\\s]*/i, \"\")\n .replace(/\\s*(Done|Complete|That'?s? it)\\.?$/i, \"\")\n .trim();\n\n // Remove annotation comments that we added for the AI\n code = code\n .replace(/\\s*\\/\\/ ← CLICKED ELEMENT STARTS/g, \"\")\n .replace(/\\s*\\/\\/ ← CLICKED ELEMENT ENDS/g, \"\")\n .replace(/\\s*\\/\\/ ← CLICKED ELEMENT \\(single line\\)/g, \"\")\n .replace(/\\s*\\/\\/ ← \\(clicked element\\)/g, \"\")\n .trim();\n\n if (!code) return \"\";\n\n // Fix indentation (only for non-full-component, since full component has its own indentation)\n if (!isFullComponent) {\n const lines = code.split(\"\\n\");\n const firstLineIndent = lines[0]?.match(/^(\\s*)/)?.[1] || \"\";\n const indentDiff = baseIndentation.length - firstLineIndent.length;\n\n if (indentDiff !== 0) {\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].trim()) {\n const currentIndent = lines[i].match(/^(\\s*)/)?.[1] || \"\";\n const newIndentLength = Math.max(\n 0,\n currentIndent.length + indentDiff,\n );\n lines[i] = \" \".repeat(newIndentLength) + lines[i].trimStart();\n }\n }\n code = lines.join(\"\\n\");\n }\n }\n\n return marker + code;\n}\n\nfunction validateGeneratedCode(newCode: string, originalCode: string, fileContent?: string): boolean {\n // Try to parse the new code as JSX\n try {\n // Check if it's a full component/function declaration\n const isFullComponent = /^(export\\s+)?(default\\s+)?function\\s+\\w+/.test(newCode.trim()) ||\n /^(export\\s+)?(default\\s+)?const\\s+\\w+\\s*=/.test(newCode.trim());\n\n if (isFullComponent) {\n // For full components, include any interface/type definitions from the original file\n let codeToValidate = newCode;\n if (fileContent) {\n const interfaceMatches = fileContent.match(/^(interface|type)\\s+\\w+[^}]*\\}/gm);\n if (interfaceMatches) {\n codeToValidate = interfaceMatches.join('\\n\\n') + '\\n\\n' + newCode;\n }\n }\n\n // Parse as a full module\n parser.parse(codeToValidate, {\n sourceType: \"module\",\n plugins: [\"jsx\", \"typescript\"],\n });\n } else {\n // Wrap in a function to make it valid\n const wrapped = `function _() { return (${newCode}); }`;\n parser.parse(wrapped, {\n sourceType: \"module\",\n plugins: [\"jsx\", \"typescript\"],\n });\n }\n } catch (e) {\n console.error(\"Generated code parse error:\", e);\n return false;\n }\n\n // Check brace/tag balance\n const origBraces = (originalCode.match(/[{}]/g) || []).length;\n const newBraces = (newCode.match(/[{}]/g) || []).length;\n const origTags = (originalCode.match(/[<>]/g) || []).length;\n const newTags = (newCode.match(/[<>]/g) || []).length;\n\n // Allow some variance but flag major differences\n if (\n Math.abs(origBraces - newBraces) > 4 ||\n Math.abs(origTags - newTags) > 4\n ) {\n console.warn(\n `Structure changed significantly: braces ${origBraces}->${newBraces}, tags ${origTags}->${newTags}`,\n );\n }\n\n return true;\n}\n\n// =============================================================================\n// UTILITIES\n// =============================================================================\n// (Path utilities moved to @/lib/ai-editor-utils)\n","// =============================================================================\n// FILE: lib/source-map-resolver.ts\n// Source map resolution utility for Next.js dev mode\n// =============================================================================\n\nimport { SourceMapConsumer } from \"@jridgewell/source-map\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\ninterface CompiledPosition {\n filePath: string;\n line: number;\n column: number;\n chunkId?: string;\n}\n\ninterface OriginalPosition {\n source: string;\n line: number;\n column: number;\n}\n\n// (SourceMapConsumer as any).initialize({\n// \"lib/mappings.wasm\": require.resolve(\"source-map/lib/mappings.wasm\"),\n// });\n\n/**\n * Parse _debugStack format to extract compiled position\n * Format: \"at ComponentName (file-path:line:column)\"\n * With turbopack, the file path is the compiled JS file path\n */\nexport function parseDebugStack(stack: string | any): CompiledPosition | null {\n if (!stack) return null;\n\n const stackStr =\n typeof stack === \"string\" ? stack : stack.stack || String(stack);\n const frames = stackStr.split(\"\\n\");\n\n const skipPatterns = [\n \"node_modules\",\n \"SegmentViewNode\",\n \"LayoutRouter\",\n \"ErrorBoundary\",\n \"fakeJSXCallSite\",\n ];\n\n for (const frame of frames) {\n if (skipPatterns.some((p) => frame.includes(p))) continue;\n\n // Match: at Name (path:line:col) or at Name (path?id:line:col)\n // Also handle file:// URLs and about://React/Server/ prefixes in the path\n const match = frame.match(/at\\s+(\\w+)\\s+\\((.+?):(\\d+):(\\d+)\\)?$/);\n if (match) {\n let filePath = match[2];\n const line = parseInt(match[3], 10);\n const column = parseInt(match[4], 10);\n\n // Extract chunk ID if present (e.g., \"path?21\" -> chunkId: \"21\")\n // Need to do this before cleaning, as the query param is before the line:col\n let chunkId: string | undefined;\n const chunkMatch = filePath.match(/\\?([^:]+)$/);\n if (chunkMatch) {\n chunkId = chunkMatch[1];\n filePath = filePath.replace(/\\?[^:]*$/, \"\");\n }\n\n // With turbopack, preserve the full file path (don't clean webpack patterns)\n // The path is already the compiled file path we need\n // Handle about://React/Server/file://... format\n filePath = cleanPathTurbopack(filePath);\n\n if (!shouldSkip(filePath)) {\n console.log(\"parseDebugStack extracted:\", { filePath, line, column });\n return { filePath, line, column, chunkId };\n }\n }\n }\n\n console.log(\n \"parseDebugStack: no valid frame found in stack:\",\n stackStr.substring(0, 200),\n );\n return null;\n}\n\n/**\n * Clean paths for turbopack - preserve full file paths, only clean protocol prefixes\n */\nfunction cleanPathTurbopack(p: string): string {\n // Remove protocol prefixes but preserve the actual file path\n // Handle about://React/Server/file://... format from React Server Components\n let cleaned = p;\n\n // Remove about://React/Server/ prefix first (this wraps file:// URLs)\n cleaned = cleaned.replace(/^about:\\/\\/React\\/Server\\//, \"\");\n\n // Remove file:// protocol (may appear after about://React/Server/)\n if (cleaned.startsWith(\"file://\")) {\n cleaned = cleaned.replace(/^file:\\/\\//, \"\");\n }\n\n // Decode URL-encoded paths (e.g., %5B becomes [, %5D becomes ])\n try {\n if (cleaned.includes(\"%\")) {\n cleaned = decodeURIComponent(cleaned);\n }\n } catch (e) {\n // If decoding fails, continue with original\n console.warn(\"Failed to decode URL-encoded path:\", cleaned, e);\n }\n\n // Remove other protocol prefixes\n cleaned = cleaned\n .replace(/^webpack-internal:\\/\\/\\/\\([^)]+\\)\\/\\.\\//, \"\")\n .replace(/^webpack-internal:\\/\\/\\/\\([^)]+\\)\\//, \"\")\n .replace(/^webpack-internal:\\/\\//, \"\")\n .replace(/^webpack:\\/\\/[^/]*\\//, \"\")\n .replace(/^\\([^)]+\\)\\//, \"\")\n .replace(/\\?.*$/, \"\");\n\n // If the path starts with .next, it's likely a compiled file path - preserve it\n if (cleaned.startsWith(\".next/\") || path.isAbsolute(cleaned)) {\n return cleaned;\n }\n\n return cleaned;\n}\n\n/**\n * Clean webpack-internal paths to get the actual file path (legacy, for non-turbopack)\n */\nfunction cleanPath(p: string): string {\n return cleanPathTurbopack(p);\n}\nfunction normalizeSourcePath(source: string, projectRoot: string): string {\n let cleaned = cleanPath(source);\n cleaned = cleaned.replace(/\\\\/g, \"/\");\n if (cleaned.startsWith(projectRoot)) {\n cleaned = cleaned.substring(projectRoot.length + 1);\n }\n return cleaned.replace(/^\\/+/, \"\");\n}\n\n/**\n * Check if path should be skipped\n */\nfunction shouldSkip(p: string): boolean {\n if (!p) return true;\n return [\"node_modules\", \"next/dist\", \"react-dom\"].some((s) => p.includes(s));\n}\n\n/**\n * Resolve original source position from compiled position\n * With turbopack, source maps are separate .map files with the same path as the compiled file\n */\nexport async function resolveOriginalPosition(\n compiledPos: CompiledPosition,\n projectRoot: string,\n): Promise<OriginalPosition | null> {\n try {\n console.log(\"resolveOriginalPosition called with:\", compiledPos);\n\n // With turbopack, the filePath from React is the compiled JS file path\n // The source map is the same path with .map appended\n let compiledFilePath = compiledPos.filePath;\n\n // Normalize the path (handle file:// URLs, URL encoding, etc.)\n compiledFilePath = cleanPathTurbopack(compiledFilePath);\n console.log(\"After cleanPathTurbopack:\", compiledFilePath);\n\n // Check if it's an HTTP URL (from dev server)\n if (compiledFilePath.startsWith(\"http://\") || compiledFilePath.startsWith(\"https://\")) {\n // Convert HTTP URL to filesystem path\n // e.g., http://localhost:3002/_next/static/chunks/... -> <projectRoot>/.next/dev/static/chunks/...\n const url = new URL(compiledFilePath);\n const pathname = url.pathname; // e.g., /_next/static/chunks/...\n\n // Map to filesystem (dev server serves from .next/dev/)\n if (pathname.startsWith(\"/_next/\")) {\n // Replace /_next/ with .next/dev/\n const relativePath = pathname.substring(\"/_next/\".length); // e.g., static/chunks/...\n compiledFilePath = path.join(projectRoot, \".next\", \"dev\", relativePath);\n } else {\n console.warn(\"Unexpected HTTP URL path:\", pathname);\n return null;\n }\n }\n // Resolve the path relative to project root\n else if (!path.isAbsolute(compiledFilePath)) {\n // If it starts with .next, it's relative to project root\n if (compiledFilePath.startsWith(\".next/\")) {\n compiledFilePath = path.resolve(projectRoot, compiledFilePath);\n } else {\n // Try to resolve as-is first\n const resolved = path.resolve(projectRoot, compiledFilePath);\n if (await fileExists(resolved)) {\n compiledFilePath = resolved;\n } else {\n // Try common locations\n const possiblePaths = [\n path.join(projectRoot, \".next\", \"dev\", compiledFilePath),\n path.join(projectRoot, compiledFilePath),\n ];\n for (const tryPath of possiblePaths) {\n if (await fileExists(tryPath)) {\n compiledFilePath = tryPath;\n break;\n }\n }\n }\n }\n }\n // If already absolute, just normalize it\n else {\n compiledFilePath = path.normalize(compiledFilePath);\n }\n\n console.log(\"Normalized compiled file path:\", compiledFilePath);\n\n // Check if the compiled file exists (for debugging)\n const compiledExists = await fileExists(compiledFilePath);\n console.log(\n \"Compiled file exists:\",\n compiledExists,\n \"at:\",\n compiledFilePath,\n );\n if (!compiledExists) {\n console.error(\n `Compiled file not found: ${compiledFilePath} (from parsed: ${compiledPos.filePath})`,\n );\n // Still try to find the source map, in case the file was moved\n }\n\n // Append .map to get the source map file path\n const sourceMapPath = compiledFilePath + \".map\";\n console.log(\"Looking for source map at:\", sourceMapPath);\n\n // Check if source map file exists\n const sourceMapExists = await fileExists(sourceMapPath);\n console.log(\"Source map exists:\", sourceMapExists);\n if (!sourceMapExists) {\n console.error(\n `Source map not found: ${sourceMapPath} (from compiled: ${compiledPos.filePath}, normalized: ${compiledFilePath})`,\n );\n // Try alternative paths\n const altPaths = [\n compiledFilePath.replace(/\\.js$/, \".map\"),\n path.join(\n path.dirname(compiledFilePath),\n path.basename(compiledFilePath) + \".map\",\n ),\n ];\n console.log(\"Trying alternative paths:\", altPaths);\n for (const altPath of altPaths) {\n if (await fileExists(altPath)) {\n console.log(\"Found source map at alternative path:\", altPath);\n return await resolveFromSourceMap(altPath, compiledPos, projectRoot);\n }\n }\n return null;\n }\n\n return await resolveFromSourceMap(sourceMapPath, compiledPos, projectRoot);\n } catch (error) {\n console.error(\"Error resolving source map:\", error);\n return null;\n }\n}\n\nasync function resolveFromSourceMap(\n sourceMapPath: string,\n compiledPos: CompiledPosition,\n projectRoot: string,\n): Promise<OriginalPosition | null> {\n try {\n // Read the source map file\n const sourceMapContent = await fs.readFile(sourceMapPath, \"utf-8\");\n const sourceMap = JSON.parse(sourceMapContent);\n\n // Handle empty source maps (common with server-side bundles)\n if (\n (!sourceMap.sources || sourceMap.sources.length === 0) &&\n (!sourceMap.sections || sourceMap.sections.length === 0)\n ) {\n console.warn(\n \"Empty source map detected, cannot resolve position:\",\n sourceMapPath,\n );\n return null;\n }\n\n // Handle sectioned source maps (turbopack uses these)\n if (sourceMap.sections) {\n // Find the section that contains our line\n // Sections are ordered by offset, find the last section that starts before our position\n // Offset is 0-indexed, compiledPos.line is 1-indexed\n let matchingSection = null;\n for (let i = sourceMap.sections.length - 1; i >= 0; i--) {\n const section = sourceMap.sections[i];\n const offset = section.offset;\n const sectionStartLine1Indexed = offset.line + 1;\n // Check if our position is at or after this section's start\n if (\n compiledPos.line > sectionStartLine1Indexed ||\n (compiledPos.line === sectionStartLine1Indexed &&\n compiledPos.column >= offset.column)\n ) {\n matchingSection = section;\n break;\n }\n }\n\n if (matchingSection && matchingSection.map) {\n const sectionMap = matchingSection.map;\n const offset = matchingSection.offset;\n\n // Use the section's source map\n let consumer: SourceMapConsumer;\n try {\n consumer = await new SourceMapConsumer(sectionMap);\n } catch (error) {\n console.error(\"Error creating SourceMapConsumer:\", error);\n return null;\n }\n try {\n // Adjust line/column relative to section offset\n // Offset is 0-indexed, source-map library uses 1-indexed lines\n // If offset is {line: 14, column: 0}, section starts at line 15 (1-indexed)\n // For compiled line 82 (1-indexed) with offset 14, adjusted line = 82 - 14 = 68 (1-indexed)\n const adjustedLine = compiledPos.line - offset.line;\n const adjustedColumn =\n compiledPos.line === offset.line + 1\n ? compiledPos.column - offset.column\n : compiledPos.column;\n\n const originalPos = consumer.originalPositionFor({\n line: adjustedLine,\n column: adjustedColumn,\n });\n\n if (originalPos.source && originalPos.line !== null) {\n const source = normalizeSourcePath(\n originalPos.source || \"\",\n projectRoot,\n );\n\n return {\n source,\n line: originalPos.line,\n column: originalPos.column ?? 0,\n };\n }\n } finally {\n consumer.destroy();\n }\n }\n return null;\n }\n\n // Handle regular (non-sectioned) source maps\n const consumer = await new SourceMapConsumer(sourceMap);\n try {\n const originalPos = consumer.originalPositionFor({\n line: compiledPos.line,\n column: compiledPos.column,\n });\n\n if (originalPos.source && originalPos.line !== null) {\n const source = normalizeSourcePath(\n originalPos.source || \"\",\n projectRoot,\n );\n\n return {\n source,\n line: originalPos.line,\n column: originalPos.column ?? 0,\n };\n }\n } finally {\n consumer.destroy();\n }\n\n return null;\n } catch (error) {\n console.error(\"Error resolving source map:\", error);\n return null;\n }\n}\n\n/**\n * Check if a file exists\n */\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Extract ALL source maps from compiled JS content (legacy, for webpack)\n * Returns array of source maps since webpack bundles can have multiple\n */\nfunction extractAllSourceMaps(content: string): any[] {\n const sourceMaps: any[] = [];\n\n // Find all inline source maps (data URLs)\n const inlinePattern =\n /\\/\\/# sourceMappingURL=data:application\\/json;charset=utf-8;base64,([A-Za-z0-9+/=]+)/g;\n let match;\n\n while ((match = inlinePattern.exec(content)) !== null) {\n try {\n const base64Data = match[1];\n const jsonStr = Buffer.from(base64Data, \"base64\").toString(\"utf-8\");\n const sourceMap = JSON.parse(jsonStr);\n sourceMaps.push(sourceMap);\n } catch (err) {\n console.error(\"Error parsing inline source map:\", err);\n }\n }\n\n return sourceMaps;\n}\n\n/**\n * Extract source map from compiled JS content (single map, for backwards compat)\n */\nfunction extractSourceMap(content: string): any | null {\n const maps = extractAllSourceMaps(content);\n return maps.length > 0 ? maps[0] : null;\n}\n\n/**\n * Helper to get original position from _debugStack\n * Combines parsing and resolution into one function\n */\nexport async function getOriginalPositionFromDebugStack(\n debugStack: string | any,\n projectRoot: string,\n): Promise<OriginalPosition | null> {\n const compiledPos = parseDebugStack(debugStack);\n if (!compiledPos) return null;\n\n return await resolveOriginalPosition(compiledPos, projectRoot);\n}\n","// =============================================================================\n// FILE: app/api/ai-editor/read/route.ts\n// =============================================================================\n\nimport { NextRequest, NextResponse } from \"next/server\";\nimport fs from \"fs/promises\";\nimport traverse from \"@babel/traverse\";\nimport type { NodePath } from \"@babel/traverse\";\nimport * as t from \"@babel/types\";\nimport {\n validateDevMode,\n normalizePath,\n resolveFilePath,\n} from \"../utils/file-system\";\nimport { parseDebugStack, resolveOriginalPosition } from \"../utils/source-map\";\nimport { parseFile, findTargetElement } from \"../utils/ast\";\nimport type { ElementContext } from \"../../shared/types\";\n\nexport async function handleRead(req: NextRequest): Promise<NextResponse> {\n const devModeError = validateDevMode();\n if (devModeError) return devModeError;\n\n const { searchParams } = new URL(req.url);\n let filePath = searchParams.get(\"path\") || \"\";\n let lineNumber = parseInt(searchParams.get(\"line\") || \"1\");\n const debugStack = searchParams.get(\"debugStack\") || \"\";\n\n // Parse element context from query params\n const tagName = searchParams.get(\"tagName\") || \"\";\n const nthOfType = parseInt(searchParams.get(\"nthOfType\") || \"0\");\n const textContent = searchParams.get(\"textContent\") || \"\";\n const className = searchParams.get(\"className\") || \"\";\n\n const elementContext: ElementContext | undefined = tagName\n ? {\n tagName,\n nthOfType: nthOfType > 0 ? nthOfType : undefined,\n textContent: textContent || undefined,\n className: className || undefined,\n }\n : undefined;\n\n const projectRoot = process.cwd();\n\n // If debugStack is provided, try to resolve original position using source maps\n if (debugStack) {\n const compiledPos = parseDebugStack(debugStack);\n if (compiledPos) {\n const originalPos = await resolveOriginalPosition(\n compiledPos,\n projectRoot,\n );\n if (originalPos) {\n filePath = originalPos.source;\n lineNumber = originalPos.line;\n }\n }\n }\n\n // Normalize and resolve file path\n const normalizedPath = normalizePath(filePath);\n const absolutePath = await resolveFilePath(projectRoot, normalizedPath);\n if (!absolutePath) {\n return NextResponse.json(\n { success: false, error: \"File not found\" },\n { status: 404 },\n );\n }\n\n const content = await fs.readFile(absolutePath, \"utf-8\");\n\n // Parse with Babel to find component and element\n const ast = parseFile(content);\n if (!ast) {\n return NextResponse.json(\n { success: false, error: \"Failed to parse file\" },\n { status: 400 },\n );\n }\n\n // Extract component name from file (try both default and named exports)\n let componentName = \"\";\n traverse(ast, {\n ExportDefaultDeclaration(path: NodePath<t.ExportDefaultDeclaration>) {\n if (t.isFunctionDeclaration(path.node.declaration)) {\n componentName = path.node.declaration.id?.name || \"\";\n }\n },\n ExportNamedDeclaration(path: NodePath<t.ExportNamedDeclaration>) {\n if (t.isFunctionDeclaration(path.node.declaration)) {\n componentName = path.node.declaration.id?.name || \"\";\n }\n },\n });\n\n if (!componentName) {\n // Fallback: return full file\n return NextResponse.json({\n success: true,\n content,\n lineStart: 1,\n lineEnd: content.split(\"\\n\").length,\n });\n }\n\n // Find component and target element using same logic as /edit\n const target = findTargetElement(ast, content, {\n componentName,\n lineNumber,\n elementContext,\n });\n\n if (!target) {\n return NextResponse.json({\n success: true,\n content,\n lineStart: 1,\n lineEnd: content.split(\"\\n\").length,\n });\n }\n\n // Log what we found for debugging\n console.log(`[/read] Found element:`);\n console.log(\n ` Component: ${componentName} (lines ${target.componentStart}-${target.componentEnd})`,\n );\n console.log(` Target element: lines ${target.startLine}-${target.endLine}`);\n console.log(\n ` Element context: tagName=${elementContext?.tagName}, nthOfType=${elementContext?.nthOfType}`,\n );\n\n // Show a preview of what we found\n const foundLines = content\n .split(\"\\n\")\n .slice(\n target.startLine - 1,\n Math.min(target.startLine + 2, target.endLine),\n );\n console.log(` Preview: ${foundLines[0]?.trim()}`);\n console.log(\n ` textContent=\"${elementContext?.textContent}\", className=\"${elementContext?.className}\"`,\n );\n\n // Return full component without markers (client will highlight visually)\n const lines = content.split(\"\\n\");\n const componentLines = lines.slice(\n target.componentStart - 1,\n target.componentEnd,\n );\n\n const preview = componentLines.join(\"\\n\");\n\n return NextResponse.json({\n success: true,\n content: preview,\n lineStart: target.componentStart,\n lineEnd: target.componentEnd,\n targetStartLine: target.startLine,\n targetEndLine: target.endLine,\n componentName, // Return the actual component name parsed from code\n });\n}\n","// =============================================================================\n// FILE: app/api/ai-editor/undo/route.ts\n// Undo endpoint - restores file content from snapshot\n// =============================================================================\n\nimport { NextRequest, NextResponse } from \"next/server\";\nimport fs from \"fs/promises\";\nimport {\n validateDevMode,\n normalizePath,\n resolveFilePath,\n isPathSecure,\n} from \"../utils/file-system\";\n\ninterface UndoRequest {\n filePath: string;\n content: string;\n}\n\nexport async function handleUndo(req: NextRequest): Promise<NextResponse> {\n const devModeError = validateDevMode();\n if (devModeError) return devModeError;\n\n try {\n const body: UndoRequest = await req.json();\n const { filePath, content } = body;\n\n if (!filePath || typeof content !== \"string\") {\n return NextResponse.json(\n {\n success: false,\n error: \"Invalid request: filePath and content required\",\n },\n { status: 400 },\n );\n }\n\n const projectRoot = process.cwd();\n const normalizedPath = normalizePath(filePath);\n const absolutePath = await resolveFilePath(projectRoot, normalizedPath);\n\n if (!absolutePath) {\n return NextResponse.json(\n { success: false, error: `File not found: ${normalizedPath}` },\n { status: 404 },\n );\n }\n\n // Security: Ensure file is within project root\n if (!isPathSecure(absolutePath, projectRoot)) {\n return NextResponse.json(\n { success: false, error: \"Access denied: File outside project root\" },\n { status: 403 },\n );\n }\n\n // Write the snapshot content back to the file\n await fs.writeFile(absolutePath, content, \"utf-8\");\n\n console.log(`✅ Undo: Restored ${normalizedPath}`);\n return NextResponse.json({ success: true });\n } catch (error) {\n console.error(\"Undo error:\", error);\n return NextResponse.json(\n { success: false, error: String(error) },\n { status: 500 },\n );\n }\n}\n","// =============================================================================\n// FILE: app/api/ai-editor/resolve/route.ts\n// Resolves compiled stack positions to original source locations\n// =============================================================================\n\nimport { NextRequest, NextResponse } from \"next/server\";\nimport { validateDevMode } from \"../utils/file-system\";\nimport {\n parseDebugStack,\n resolveOriginalPosition,\n} from \"../utils/source-map\";\n\nexport async function handleResolve(req: NextRequest): Promise<NextResponse> {\n const devModeError = validateDevMode();\n if (devModeError) return devModeError;\n\n try {\n const body = await req.json();\n const debugStack = body?.debugStack;\n\n if (!debugStack || typeof debugStack !== \"string\") {\n return NextResponse.json(\n { success: false, error: \"Missing debugStack\" },\n { status: 400 },\n );\n }\n\n const compiledPos = parseDebugStack(debugStack);\n if (!compiledPos) {\n console.error(\"Could not parse debug stack:\", debugStack);\n return NextResponse.json(\n { success: false, error: \"Could not parse stack\" },\n { status: 422 },\n );\n }\n\n console.log(\"Parsed compiled position:\", compiledPos);\n\n const originalPos = await resolveOriginalPosition(\n compiledPos,\n process.cwd(),\n );\n\n if (!originalPos) {\n console.error(\n \"Source map lookup failed for:\",\n compiledPos.filePath,\n \"at line\",\n compiledPos.line,\n );\n return NextResponse.json(\n { success: false, error: \"Source map lookup failed\" },\n { status: 404 },\n );\n }\n\n console.log(\"Resolved original position:\", originalPos);\n\n return NextResponse.json({\n success: true,\n filePath: originalPos.source,\n lineNumber: originalPos.line,\n columnNumber: originalPos.column ?? 0,\n });\n } catch (error) {\n console.error(\"Source resolve error:\", error);\n return NextResponse.json(\n { success: false, error: \"Internal error\" },\n { status: 500 },\n );\n }\n}\n","// =============================================================================\n// FILE: app/api/ai-editor/absolute-path/route.ts\n// =============================================================================\n\nimport { NextRequest, NextResponse } from \"next/server\";\nimport {\n validateDevMode,\n normalizePath,\n resolveFilePath,\n} from \"../utils/file-system\";\n\nexport async function handleAbsolutePath(req: NextRequest): Promise<NextResponse> {\n const devModeError = validateDevMode();\n if (devModeError) return devModeError;\n\n const { searchParams } = new URL(req.url);\n const filePath = searchParams.get(\"path\") || \"\";\n\n if (!filePath) {\n return NextResponse.json(\n { success: false, error: \"Missing path\" },\n { status: 400 },\n );\n }\n\n const projectRoot = process.cwd();\n const normalizedPath = normalizePath(filePath);\n const absolutePath = await resolveFilePath(projectRoot, normalizedPath);\n\n if (!absolutePath) {\n return NextResponse.json(\n { success: false, error: \"File not found\" },\n { status: 404 },\n );\n }\n\n return NextResponse.json({\n success: true,\n absolutePath,\n });\n}\n","// =============================================================================\n// FILE: app/api/ai-editor/validate-session/route.ts\n// Validates session by checking if file has been modified externally\n// =============================================================================\n\nimport { NextRequest, NextResponse } from \"next/server\";\nimport fs from \"fs/promises\";\nimport crypto from \"crypto\";\nimport {\n validateDevMode,\n normalizePath,\n resolveFilePath,\n isPathSecure,\n} from \"../utils/file-system\";\n\nexport async function handleValidateSession(req: NextRequest): Promise<NextResponse> {\n const devModeError = validateDevMode();\n if (devModeError) return devModeError;\n\n try {\n const body = await req.json();\n const { filePath, lastKnownHash, lastKnownSize } = body;\n\n if (!filePath || !lastKnownHash || lastKnownSize === undefined) {\n return NextResponse.json(\n { success: false, error: \"Missing required fields\" },\n { status: 400 }\n );\n }\n\n const projectRoot = process.cwd();\n const normalizedPath = normalizePath(filePath);\n const absolutePath = await resolveFilePath(projectRoot, normalizedPath);\n\n if (!absolutePath) {\n return NextResponse.json(\n { success: false, error: \"File not found\" },\n { status: 404 }\n );\n }\n\n if (!isPathSecure(absolutePath, projectRoot)) {\n return NextResponse.json(\n { success: false, error: \"Access denied\" },\n { status: 403 }\n );\n }\n\n // Read file content\n const content = await fs.readFile(absolutePath, \"utf-8\");\n\n // Compute SHA-256 hash\n const hash = crypto.createHash(\"sha256\").update(content).digest(\"hex\");\n\n // Get file stats\n const stats = await fs.stat(absolutePath);\n\n // Check if file has changed\n const isValid =\n hash === lastKnownHash && content.length === lastKnownSize;\n\n console.log(`[validate-session] ${filePath}:`);\n console.log(` Hash match: ${hash === lastKnownHash}`);\n console.log(` Size match: ${content.length === lastKnownSize}`);\n console.log(` Is valid: ${isValid}`);\n\n return NextResponse.json({\n success: true,\n isValid,\n currentHash: hash,\n currentSize: content.length,\n lastModifiedTime: stats.mtimeMs,\n });\n } catch (error) {\n console.error(\"Validation error:\", error);\n return NextResponse.json(\n { success: false, error: String(error) },\n { status: 500 }\n );\n }\n}\n","// =============================================================================\n// FILE: src/server/handlers/index.ts\n// Unified catch-all handler for AI editor routes\n// =============================================================================\n\nimport { NextRequest, NextResponse } from \"next/server\";\nimport { handleEdit } from \"./edit\";\nimport { handleRead } from \"./read\";\nimport { handleUndo } from \"./undo\";\nimport { handleResolve } from \"./resolve\";\nimport { handleAbsolutePath } from \"./absolute-path\";\nimport { handleValidateSession } from \"./validate-session\";\n\n/**\n * Catch-all handler for AI editor routes\n *\n * Route mapping:\n * - POST /api/ai-editor/edit -> handleEdit\n * - GET /api/ai-editor/read -> handleRead\n * - POST /api/ai-editor/undo -> handleUndo\n * - POST /api/ai-editor/resolve -> handleResolve\n * - GET /api/ai-editor/absolute-path -> handleAbsolutePath\n * - POST /api/ai-editor/validate-session -> handleValidateSession\n */\nexport async function handleAIEditorRequest(\n req: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n): Promise<NextResponse> {\n const { path } = await context.params;\n const endpoint = path[0];\n const method = req.method;\n\n switch (endpoint) {\n case \"edit\":\n if (method === \"POST\") return handleEdit(req);\n break;\n case \"read\":\n if (method === \"GET\") return handleRead(req);\n break;\n case \"undo\":\n if (method === \"POST\") return handleUndo(req);\n break;\n case \"resolve\":\n if (method === \"POST\") return handleResolve(req);\n break;\n case \"absolute-path\":\n if (method === \"GET\") return handleAbsolutePath(req);\n break;\n case \"validate-session\":\n if (method === \"POST\") return handleValidateSession(req);\n break;\n }\n\n return NextResponse.json(\n { error: `Unknown endpoint: ${endpoint}` },\n { status: 404 }\n );\n}\n"],"names":["fileExists","path","consumer","_a"],"mappings":"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"}