next-ai-editor 0.1.1 → 0.1.3

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-Bs9zUVrL.cjs → AIEditorProvider-BGHm2xyU.cjs} +823 -378
  2. package/dist/AIEditorProvider-BGHm2xyU.cjs.map +1 -0
  3. package/dist/{AIEditorProvider-D-w9-GZb.js → AIEditorProvider-CxdGjdLL.js} +847 -402
  4. package/dist/AIEditorProvider-CxdGjdLL.js.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-DnoYi4f8.cjs → index-CNJqd4EQ.cjs} +656 -225
  16. package/dist/index-CNJqd4EQ.cjs.map +1 -0
  17. package/dist/{index-BFa7H-uO.js → index-DrmEf13c.js} +662 -231
  18. package/dist/index-DrmEf13c.js.map +1 -0
  19. package/dist/index.cjs +7 -2
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.js +15 -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 +10 -0
  38. package/dist/server/utils/source-map.d.ts.map +1 -1
  39. package/dist/server.cjs +6 -1
  40. package/dist/server.cjs.map +1 -1
  41. package/dist/server.js +14 -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":"index-DnoYi4f8.cjs","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":["NextResponse","fileExists","parser","path","t","ChatAnthropic","SystemMessage","HumanMessage","sourceMap","consumer","SourceMapConsumer","_a"],"mappings":"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"}