next-ai-editor 0.2.1 → 0.2.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.
- package/dist/{AIEditorProvider-C_zRSAuV.cjs → AIEditorProvider-CLgf1Vwa.cjs} +247 -186
- package/dist/AIEditorProvider-CLgf1Vwa.cjs.map +1 -0
- package/dist/{AIEditorProvider-CKA2K_g2.js → AIEditorProvider-DWId5Qmv.js} +248 -187
- package/dist/AIEditorProvider-DWId5Qmv.js.map +1 -0
- package/dist/client/AIEditorProvider.d.ts +10 -1
- package/dist/client/AIEditorProvider.d.ts.map +1 -1
- package/dist/client/components/ChatPanel.d.ts.map +1 -1
- package/dist/client/components/ControlPill.d.ts +1 -1
- package/dist/client/components/ControlPill.d.ts.map +1 -1
- package/dist/client.cjs +1 -1
- package/dist/client.js +1 -1
- package/dist/{comments-D3m0RsOO.js → comments-BcCC35iA.js} +12 -1
- package/dist/comments-BcCC35iA.js.map +1 -0
- package/dist/{comments-Daur80r4.cjs → comments-BpGGRaC9.cjs} +12 -1
- package/dist/comments-BpGGRaC9.cjs.map +1 -0
- package/dist/index.cjs +2 -2
- package/dist/index.js +2 -2
- package/dist/next-ai-editor.css +215 -109
- package/dist/server/handlers/config.d.ts +7 -0
- package/dist/server/handlers/config.d.ts.map +1 -0
- package/dist/server/handlers/index.d.ts.map +1 -1
- package/dist/server.cjs +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
- package/dist/AIEditorProvider-CKA2K_g2.js.map +0 -1
- package/dist/AIEditorProvider-C_zRSAuV.cjs.map +0 -1
- package/dist/comments-D3m0RsOO.js.map +0 -1
- package/dist/comments-Daur80r4.cjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"comments-Daur80r4.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/suggestions.ts","../src/server/agent/sdk-client.ts","../src/server/agent/session-store.ts","../src/server/handlers/chat.ts","../src/server/handlers/index.ts","../src/server/handlers/comments.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 * Extract the component name from an AST\n * Looks for both default and named exports\n */\nexport function extractComponentName(ast: t.File): string | null {\n let componentName: string | null = null;\n\n traverse(ast, {\n ExportDefaultDeclaration(path: NodePath<t.ExportDefaultDeclaration>) {\n if (t.isFunctionDeclaration(path.node.declaration)) {\n componentName = path.node.declaration.id?.name || null;\n } else if (t.isArrowFunctionExpression(path.node.declaration)) {\n // Handle: export default () => <div>...</div>\n componentName = \"default\";\n } else if (t.isIdentifier(path.node.declaration)) {\n // Handle: const Foo = () => {}; export default Foo;\n componentName = path.node.declaration.name;\n }\n },\n ExportNamedDeclaration(path: NodePath<t.ExportNamedDeclaration>) {\n if (t.isFunctionDeclaration(path.node.declaration)) {\n componentName = path.node.declaration.id?.name || null;\n } else if (t.isVariableDeclaration(path.node.declaration)) {\n // Handle: export const Foo = () => {}\n const declarator = path.node.declaration.declarations[0];\n if (t.isIdentifier(declarator.id)) {\n componentName = declarator.id.name;\n }\n } else if (path.node.specifiers && path.node.specifiers.length > 0) {\n // Handle: function Foo() {}; export { Foo };\n const specifier = path.node.specifiers[0];\n if (t.isExportSpecifier(specifier) && t.isIdentifier(specifier.exported)) {\n componentName = specifier.exported.name;\n }\n }\n },\n });\n\n return componentName;\n}\n\n// =============================================================================\n// VALIDATION\n// =============================================================================\n\n/**\n * Validate that generated code is syntactically correct\n * Checks if code can be parsed and maintains reasonable structure balance\n */\nexport function validateGeneratedCode(\n newCode: string,\n originalCode: string,\n fileContent?: string,\n): 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 =\n /^(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(\n /^(interface|type)\\s+\\w+[^}]*\\}/gm,\n );\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// 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\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 const elementsAtLine: ElementMatch[] = [];\n\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 // Collect elements that start at the target line number\n if (startLine === lineNumber) {\n elementsAtLine.push({ node: path.node, startLine, endLine, score: 0 });\n }\n },\n });\n\n // Strategy 1: If we have elements at the exact line, use those (TRUST THE LINE NUMBER)\n if (elementsAtLine.length > 0) {\n // If only one element at this line, use it\n if (elementsAtLine.length === 1) {\n const target = elementsAtLine[0];\n return {\n startLine: target.startLine,\n endLine: target.endLine,\n componentStart,\n componentEnd,\n };\n }\n\n // Multiple elements at this line - use element context to disambiguate\n if (elementContext) {\n for (const elem of elementsAtLine) {\n if (t.isJSXElement(elem.node)) {\n const score = scoreElementMatch(elem.node, elementContext, fileContent);\n elem.score = score;\n }\n }\n elementsAtLine.sort((a, b) => b.score - a.score);\n\n if (elementsAtLine[0].score > 0) {\n return {\n startLine: elementsAtLine[0].startLine,\n endLine: elementsAtLine[0].endLine,\n componentStart,\n componentEnd,\n };\n }\n }\n\n // No element context or no good match, just use first element\n return {\n startLine: elementsAtLine[0].startLine,\n endLine: elementsAtLine[0].endLine,\n componentStart,\n componentEnd,\n };\n }\n\n // Strategy 2: Use element context to match (when no exact line match)\n if (elementContext?.tagName) {\n const allOfTag = allElementsByTag.get(elementContext.tagName);\n if (allOfTag && allOfTag.length > 0) {\n // If we have textContent or other context, score all elements and pick the best match\n if (elementContext.textContent || elementContext.className) {\n for (const elem of allOfTag) {\n if (t.isJSXElement(elem.node)) {\n elem.score = scoreElementMatch(elem.node, elementContext, fileContent);\n }\n }\n allOfTag.sort((a, b) => b.score - a.score);\n\n // Return the best match if it has a good score\n if (allOfTag[0].score > 50) { // 50 is the base score for tag name match\n return {\n startLine: allOfTag[0].startLine,\n endLine: allOfTag[0].endLine,\n componentStart,\n componentEnd,\n };\n }\n }\n\n // Otherwise, use nthOfType if provided\n if (elementContext.nthOfType && allOfTag.length >= elementContext.nthOfType) {\n const target = allOfTag[elementContext.nthOfType - 1];\n return {\n startLine: target.startLine,\n endLine: target.endLine,\n componentStart,\n componentEnd,\n };\n }\n }\n }\n\n // Strategy 3: Fallback - search nearby\n const nearbyElements: ElementMatch[] = [];\n\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 if (startLine < componentStart || endLine > componentEnd) return;\n\n // Within 5 lines\n if (Math.abs(startLine - lineNumber) <= 5) {\n const score = elementContext\n ? scoreElementMatch(path.node, elementContext, fileContent)\n : 100 - Math.abs(startLine - lineNumber);\n nearbyElements.push({ node: path.node, startLine, endLine, score });\n }\n },\n });\n\n if (nearbyElements.length > 0) {\n nearbyElements.sort((a, b) => b.score - a.score);\n return {\n startLine: nearbyElements[0].startLine,\n endLine: nearbyElements[0].endLine,\n componentStart,\n componentEnd,\n };\n }\n\n // Strategy 4: Ultimate fallback - return component bounds\n if (componentNode && componentStart > 0) {\n return {\n startLine: componentStart,\n endLine: componentEnd,\n componentStart,\n componentEnd,\n };\n }\n\n return null;\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 { 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 validateGeneratedCode,\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 parentInstance?: {\n filePath: string;\n content: string;\n lineStart: number;\n lineEnd: number;\n usageLineStart: number;\n usageLineEnd: number;\n componentName: string;\n };\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 parentInstance,\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 // 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 // Extract the code to modify\n const lines = fileContent.split(\"\\n\");\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 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 parentInstance,\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 decided to edit parent instance instead\n const parentInstanceMatch = newCode.match(/\\/\\/ EDIT_PARENT_INSTANCE\\s*\\n([\\s\\S]+)/);\n\n if (parentInstanceMatch && parentInstance) {\n const parentCode = parentInstanceMatch[1].trim();\n\n // Resolve parent file path\n const parentNormalizedPath = normalizePath(parentInstance.filePath);\n const parentAbsolutePath = await resolveFilePath(projectRoot, parentNormalizedPath);\n\n if (!parentAbsolutePath) {\n return NextResponse.json({\n success: false,\n error: `Parent file not found: ${parentNormalizedPath}`,\n });\n }\n\n const parentFileContent = await fs.readFile(parentAbsolutePath, \"utf-8\");\n const parentLines = parentFileContent.split(\"\\n\");\n\n // Replace the parent component\n const newParentLines = [...parentLines];\n newParentLines.splice(\n parentInstance.lineStart - 1,\n parentInstance.lineEnd - parentInstance.lineStart + 1,\n ...parentCode.split(\"\\n\"),\n );\n\n await fs.writeFile(parentAbsolutePath, newParentLines.join(\"\\n\"), \"utf-8\");\n\n return NextResponse.json({\n success: true,\n fileSnapshot: parentFileContent,\n generatedCode: parentCode,\n modifiedLines: {\n start: parentInstance.lineStart,\n end: parentInstance.lineEnd,\n },\n editedFile: parentInstance.filePath, // Indicate which file was edited\n });\n }\n\n // Check if AI returned full component or just target element\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 // Safety check: detect if AI returned full component without marker\n const isFullComponentDeclaration = /^(export\\s+)?(default\\s+)?function\\s+\\w+/.test(newCode.trim()) ||\n /^(export\\s+)?const\\s+\\w+\\s*=/.test(newCode.trim());\n\n if (fullComponentMatch) {\n // Extract just the full component code after the marker\n codeToApply = fullComponentMatch[1].trim();\n startLineToReplace = target.componentStart;\n endLineToReplace = target.componentEnd;\n } else if (isFullComponentDeclaration && target.startLine !== target.componentStart) {\n // AI returned full component but forgot the marker!\n codeToApply = newCode;\n startLineToReplace = target.componentStart;\n endLineToReplace = target.componentEnd;\n }\n\n // Validate the generated code parses correctly\n if (!validateGeneratedCode(codeToApply, targetCode, fileContent)) {\n return NextResponse.json({\n success: false,\n error: \"Generated code is invalid\",\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 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 editedFile: filePath, // Indicate which file was edited\n });\n } catch (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 parentInstance?: {\n filePath: string;\n content: string;\n lineStart: number;\n lineEnd: number;\n usageLineStart: number;\n usageLineEnd: number;\n componentName: string;\n };\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 parentInstance,\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- Component Definition: Full code of the clicked component with line annotations\n * The clicked element is marked with \"// ← CLICKED ELEMENT STARTS\" and \"// ← CLICKED ELEMENT ENDS\"\n * These are just annotations - NOT part of the actual code\n${parentInstance ? `- Parent Instance: Where this component is used, with \"// ← COMPONENT USAGE\" marking the usage line` : ''}\n\nYOUR DECISION - Choose ONE approach based on the user's request:\n\n1. EDIT COMPONENT DEFINITION (most common):\n - Modify styling, layout, or behavior that should apply to ALL instances\n - Example requests: \"make the button blue\", \"add padding\", \"change font size\"\n - Output: Just the modified element OR \"// FULL_COMPONENT\\\\n\" + complete modified component\n\n${parentInstance ? `2. EDIT PARENT INSTANCE (when user wants to modify THIS specific usage):\n - Change props, text, or configuration for THIS specific instance only\n - Example requests: \"change this title to...\", \"remove this card\", \"add another button here\"\n - Output: \"// EDIT_PARENT_INSTANCE\\\\n\" + complete modified parent component` : ''}\n\nRULES:\n- Output ONLY code, no explanations\n- No markdown fences\n- Do NOT include annotation comments in your output\n- Preserve indentation\n- Make minimal changes`;\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 DEFINITION (clicked element is annotated):\n\n\\`\\`\\`jsx\n${fullComponentCode}\n\\`\\`\\`\n`;\n\n // Add parent instance if available\n if (parentInstance) {\n // Annotate the parent instance to show where the component is used\n const parentLines = parentInstance.content.split('\\n');\n const annotatedParentLines = parentLines.map((line, idx) => {\n const lineNum = parentInstance.lineStart + idx;\n const isUsageLine = lineNum >= parentInstance.usageLineStart && lineNum <= parentInstance.usageLineEnd;\n return line + (isUsageLine ? ' // ← COMPONENT USAGE' : '');\n });\n\n userPrompt += `\nPARENT INSTANCE (where component is used - in ${parentInstance.filePath}):\n\n\\`\\`\\`jsx\n${annotatedParentLines.join('\\n')}\n\\`\\`\\`\n`;\n }\n\n userPrompt += `\nUser request: \"${suggestion}\"\n${editHistory.length > 0 ? \"(Build upon previous changes)\" : \"\"}\n\n${parentInstance ?\n`Decide whether to:\n1. Edit the component definition (for changes that affect ALL instances)\n2. Edit the parent instance (for changes specific to THIS usage)\n\nThen output the appropriate code with the correct marker.` :\n`Modify 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 return null;\n }\n}\n\nfunction cleanGeneratedCode(code: string, baseIndentation: string): string {\n // Check if this is a parent instance edit (preserve the marker)\n const isParentEdit = code.trim().startsWith(\"// EDIT_PARENT_INSTANCE\");\n if (isParentEdit) {\n const marker = \"// EDIT_PARENT_INSTANCE\\n\";\n code = code.replace(/^\\/\\/ EDIT_PARENT_INSTANCE\\n?/, \"\");\n // Clean and return early for parent edits\n code = code\n .replace(/^```[\\w]*\\n?/gm, \"\")\n .replace(/\\n?```$/gm, \"\")\n .replace(/\\s*\\/\\/ ← COMPONENT USAGE/g, \"\")\n .trim();\n return marker + code;\n }\n\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\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\";\nimport { cleanPath, normalizeSourcePath, shouldSkipPath } from \"../../shared/path-utils\";\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 = cleanPath(filePath);\n\n if (!shouldSkipPath(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 * Extract component name from debug stack\n * Format: \"at ComponentName (file-path:line:column)\"\n */\nexport function extractComponentNameFromStack(stack: string | any): string | 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 \"react_stack_bottom_frame\",\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+\\(/);\n if (match && match[1]) {\n const componentName = match[1];\n // Skip generic names\n if (componentName !== \"Object\" && componentName !== \"anonymous\") {\n return componentName;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Parse debug stack to extract both component instance (parent) and definition\n * Returns up to 2 frames: [componentDefinition, parentInstance]\n */\nexport function parseDebugStackFrames(stack: string | any): CompiledPosition[] {\n if (!stack) return [];\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 \"react_stack_bottom_frame\",\n ];\n\n const positions: CompiledPosition[] = [];\n\n for (const frame of frames) {\n if (skipPatterns.some((p) => frame.includes(p))) continue;\n\n const match = frame.match(/at\\s+(\\w+)\\s+\\((.+?):(\\d+):(\\d+)\\)?$/);\n if (match) {\n const componentName = match[1];\n let filePath = match[2];\n const line = parseInt(match[3], 10);\n const column = parseInt(match[4], 10);\n\n // Extract chunk ID\n let chunkId: string | undefined;\n const chunkMatch = filePath.match(/\\?([^:]+)$/);\n if (chunkMatch) {\n chunkId = chunkMatch[1];\n filePath = filePath.replace(/\\?[^:]*$/, \"\");\n }\n\n filePath = cleanPath(filePath);\n\n if (!shouldSkipPath(filePath)) {\n positions.push({ filePath, line, column, chunkId });\n\n // Get up to 2 frames: component definition and parent instance\n if (positions.length >= 2) break;\n }\n }\n }\n\n console.log(`parseDebugStackFrames extracted ${positions.length} frames:`, positions);\n return positions;\n}\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 = cleanPath(compiledFilePath);\n console.log(\"After cleanPath:\", 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 {\n validateDevMode,\n normalizePath,\n resolveFilePath,\n} from \"../utils/file-system\";\nimport { parseDebugStack, resolveOriginalPosition, extractComponentNameFromStack } from \"../utils/source-map\";\nimport {\n parseFile,\n findTargetElement,\n extractComponentName,\n} 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 // Parse parent component from query params (from Fiber tree traversal)\n const parentFilePath = searchParams.get(\"parentFilePath\") || \"\";\n const parentLine = parseInt(searchParams.get(\"parentLine\") || \"0\");\n const parentComponentName = searchParams.get(\"parentComponentName\") || \"\";\n const parentDebugStack = searchParams.get(\"parentDebugStack\") || \"\";\n const childKey = searchParams.get(\"childKey\") || \"\"; // React key of child component instance\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 const componentName = extractComponentName(ast);\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\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 // Get parent instance context from client-provided data (Fiber tree traversal)\n let parentInstance = null;\n if (parentDebugStack) {\n try {\n // Resolve parent file path from debugStack\n let resolvedParentPath = parentFilePath;\n let resolvedParentLine = parentLine;\n let resolvedParentComponentName = parentComponentName;\n\n // Extract component name from debugStack if not provided by client\n if (!resolvedParentComponentName && parentDebugStack) {\n resolvedParentComponentName = extractComponentNameFromStack(parentDebugStack) || '';\n }\n\n // Parse debugStack to resolve the parent's position from its debugLocation\n if (parentDebugStack) {\n const compiledPos = parseDebugStack(parentDebugStack);\n if (compiledPos) {\n const originalPos = await resolveOriginalPosition(\n compiledPos,\n projectRoot,\n );\n if (originalPos) {\n resolvedParentPath = originalPos.source;\n resolvedParentLine = originalPos.line;\n }\n }\n }\n\n const normalizedParentPath = normalizePath(resolvedParentPath);\n const absoluteParentPath = await resolveFilePath(\n projectRoot,\n normalizedParentPath,\n );\n\n if (absoluteParentPath && resolvedParentComponentName) {\n const parentContent = await fs.readFile(absoluteParentPath, \"utf-8\");\n const parentAst = parseFile(parentContent);\n\n if (parentAst) {\n // Search for the specific child component usage within the parent\n // e.g., find <InfoBox /> or <Header /> within Home component\n\n // If childKey is provided and numeric, use it to find the specific instance\n let nthOfType: number | undefined = undefined;\n if (childKey) {\n const keyAsNumber = parseInt(childKey, 10);\n if (!isNaN(keyAsNumber)) {\n // Key is numeric (e.g., \"0\", \"1\", \"2\" from array.map((item, index) => ...))\n // Convert to 1-indexed nthOfType\n nthOfType = keyAsNumber + 1;\n }\n }\n\n const parentTarget = findTargetElement(parentAst, parentContent, {\n componentName: resolvedParentComponentName,\n lineNumber: 0, // Don't use line number - rely on element context to find correct instance\n elementContext: {\n tagName: componentName, // Search for child component usage\n nthOfType, // Find specific instance if key is numeric\n textContent: textContent || undefined, // Use text content to match the specific instance\n },\n });\n\n if (parentTarget) {\n const parentLines = parentContent.split(\"\\n\");\n const parentComponentLines = parentLines.slice(\n parentTarget.componentStart - 1,\n parentTarget.componentEnd,\n );\n\n parentInstance = {\n filePath: resolvedParentPath,\n content: parentComponentLines.join(\"\\n\"),\n lineStart: parentTarget.componentStart,\n lineEnd: parentTarget.componentEnd,\n usageLineStart: parentTarget.startLine,\n usageLineEnd: parentTarget.endLine,\n componentName: resolvedParentComponentName,\n };\n }\n }\n }\n } catch (error) {\n // Non-fatal, continue without parent instance\n console.error(\"Error resolving parent instance:\", error);\n }\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 parentInstance, // Optional: where this component is used\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 parseDebugStackFrames,\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 // Parse multiple frames to get both component definition and parent instance\n const compiledFrames = parseDebugStackFrames(debugStack);\n\n if (compiledFrames.length === 0) {\n // Fallback to single frame parsing for backward compatibility\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 const originalPos = await resolveOriginalPosition(\n compiledPos,\n process.cwd(),\n );\n\n if (!originalPos) {\n return NextResponse.json(\n { success: false, error: \"Source map lookup failed\" },\n { status: 404 },\n );\n }\n\n return NextResponse.json({\n success: true,\n filePath: originalPos.source,\n lineNumber: originalPos.line,\n columnNumber: originalPos.column ?? 0,\n });\n }\n\n // Resolve all frames\n const resolvedFrames = [];\n for (const frame of compiledFrames) {\n const originalPos = await resolveOriginalPosition(frame, process.cwd());\n if (originalPos) {\n resolvedFrames.push({\n filePath: originalPos.source,\n lineNumber: originalPos.line,\n columnNumber: originalPos.column ?? 0,\n });\n }\n }\n\n if (resolvedFrames.length === 0) {\n return NextResponse.json(\n { success: false, error: \"Source map lookup failed for all frames\" },\n { status: 404 },\n );\n }\n\n console.log(\"Resolved frames:\", resolvedFrames);\n\n // Return primary frame for backward compatibility, plus all frames\n return NextResponse.json({\n success: true,\n filePath: resolvedFrames[0].filePath,\n lineNumber: resolvedFrames[0].lineNumber,\n columnNumber: resolvedFrames[0].columnNumber,\n frames: resolvedFrames, // [componentDefinition, parentInstance]\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: app/api/ai-editor/suggestions/route.ts\n// AI-generated contextual suggestions for quick edits\n// =============================================================================\n\nimport { NextRequest, NextResponse } from \"next/server\";\nimport { ChatAnthropic } from \"@langchain/anthropic\";\nimport { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\nimport { validateDevMode } from \"../utils/file-system\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface EditHistoryItem {\n suggestion: string;\n success: boolean;\n}\n\ninterface CacheEntry {\n suggestions: string[];\n timestamp: number;\n}\n\n// =============================================================================\n// CACHE\n// =============================================================================\n\nconst suggestionCache = new Map<string, CacheEntry>();\nconst CACHE_TTL = 30000; // 30 seconds\n\nfunction getCacheKey(params: {\n componentName: string;\n elementTag?: string;\n lastSuggestion?: string;\n}): string {\n return `${params.componentName}:${params.elementTag || \"div\"}:${\n params.lastSuggestion || \"\"\n }`;\n}\n\nfunction getCachedSuggestions(key: string): string[] | null {\n const cached = suggestionCache.get(key);\n if (cached && Date.now() - cached.timestamp < CACHE_TTL) {\n return cached.suggestions;\n }\n suggestionCache.delete(key);\n return null;\n}\n\nfunction cacheSuggestions(key: string, suggestions: string[]): void {\n suggestionCache.set(key, { suggestions, timestamp: Date.now() });\n\n // Cleanup old entries (keep cache size manageable)\n if (suggestionCache.size > 100) {\n const oldestKeys = Array.from(suggestionCache.entries())\n .sort((a, b) => a[1].timestamp - b[1].timestamp)\n .slice(0, 20)\n .map(([key]) => key);\n oldestKeys.forEach((key) => suggestionCache.delete(key));\n }\n}\n\n// =============================================================================\n// DEFAULT SUGGESTIONS\n// =============================================================================\n\nconst DEFAULT_SUGGESTIONS = [\n \"Add padding\",\n \"Change color\",\n \"Make larger\",\n \"Add shadow\",\n \"Round corners\",\n \"Center content\",\n \"Add hover effect\",\n \"Adjust spacing\",\n];\n\n// =============================================================================\n// MAIN HANDLER\n// =============================================================================\n\nexport async function handleSuggestions(\n req: NextRequest,\n): Promise<NextResponse> {\n const devModeError = validateDevMode();\n if (devModeError) return devModeError;\n\n try {\n const { searchParams } = new URL(req.url);\n const componentName = searchParams.get(\"componentName\") || \"Component\";\n const elementTag = searchParams.get(\"elementTag\") || undefined;\n const className = searchParams.get(\"className\") || undefined;\n const textContent = searchParams.get(\"textContent\") || undefined;\n const lastSuggestion = searchParams.get(\"lastSuggestion\") || undefined;\n const editHistoryStr = searchParams.get(\"editHistory\") || undefined;\n const excludedSuggestionsStr =\n searchParams.get(\"excludedSuggestions\") || undefined;\n\n let editHistory: EditHistoryItem[] = [];\n if (editHistoryStr) {\n try {\n editHistory = JSON.parse(editHistoryStr);\n } catch (e) {\n // Invalid JSON, ignore\n }\n }\n\n let excludedSuggestions: string[] = [];\n if (excludedSuggestionsStr) {\n try {\n excludedSuggestions = JSON.parse(excludedSuggestionsStr);\n } catch (e) {\n // Invalid JSON, ignore\n }\n }\n\n // Check cache (skip if we're excluding suggestions)\n const cacheKey = getCacheKey({ componentName, elementTag, lastSuggestion });\n const cached =\n excludedSuggestions.length === 0 ? getCachedSuggestions(cacheKey) : null;\n if (cached) {\n return NextResponse.json({\n success: true,\n suggestions: cached,\n });\n }\n\n // Generate suggestions with AI\n const suggestions = await generateSuggestions({\n componentName,\n elementTag,\n className,\n textContent,\n editHistory,\n lastSuggestion,\n excludedSuggestions,\n });\n\n if (suggestions && suggestions.length > 0) {\n // Cache the result\n cacheSuggestions(cacheKey, suggestions);\n\n return NextResponse.json({\n success: true,\n suggestions,\n });\n }\n\n // Fallback to defaults\n return NextResponse.json({\n success: true,\n suggestions: DEFAULT_SUGGESTIONS,\n });\n } catch (error) {\n return NextResponse.json(\n {\n success: false,\n error: String(error),\n suggestions: DEFAULT_SUGGESTIONS, // Fallback\n },\n { status: 500 },\n );\n }\n}\n\n// =============================================================================\n// AI SUGGESTION GENERATION\n// =============================================================================\n\nasync function generateSuggestions(options: {\n componentName: string;\n elementTag?: string;\n className?: string;\n textContent?: string;\n editHistory: EditHistoryItem[];\n lastSuggestion?: string;\n excludedSuggestions?: string[];\n}): Promise<string[] | null> {\n const {\n componentName,\n elementTag,\n className,\n textContent,\n editHistory,\n lastSuggestion,\n excludedSuggestions = [],\n } = options;\n\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n return null;\n }\n\n const model = new ChatAnthropic({\n apiKey,\n modelName: \"claude-haiku-4-5-20251001\",\n maxTokens: 1024,\n temperature: 0.3, // Slightly creative for variety\n });\n\n const systemPrompt = `You are a UI/UX expert suggesting quick edits for React components.\n\nGenerate 6-8 concise, actionable suggestions that a developer might want to make next.\n\nRULES:\n- Each suggestion must be 2-6 words (e.g., \"Add padding\", \"Make text larger\")\n- Focus on common UI improvements: spacing, colors, sizing, layout, shadows, borders, typography\n- Consider the element type (${elementTag || \"element\"})\n- Output ONLY a JSON array of strings, no explanations, no markdown fences\n${\n excludedSuggestions.length > 0\n ? `- DO NOT suggest any of these (user wants different options): ${excludedSuggestions.join(\n \", \",\n )}`\n : \"\"\n}\n\n${\n lastSuggestion\n ? `IMPORTANT - LAST EDIT CONTEXT:\nThe user just applied: \"${lastSuggestion}\"\nYour suggestions MUST be direct follow-ups/refinements of this last change:\n- If it was \"Add padding\" → suggest \"More padding\", \"Less padding\", \"Add vertical padding only\"\n- If it was \"Make it blue\" → suggest \"Darker blue\", \"Lighter blue\", \"Change to navy blue\"\n- If it was \"Increase font size\" → suggest \"Decrease font size\", \"Make even larger\", \"Adjust line height\"\n- 4-6 suggestions should be variations/refinements of the last edit\n- 2-4 suggestions can be other related improvements\n\nGenerate follow-up suggestions that let the user iteratively refine what they just did.`\n : `Generate varied initial suggestions covering different aspects: layout, colors, spacing, shadows, typography, etc.`\n}\n\nExample output format:\n[\"Add hover effect\", \"Increase padding\", \"Make corners rounder\", \"Change to flex row\", \"Add drop shadow\", \"Adjust font size\"]`;\n\n let userPrompt = `Element: <${elementTag || \"div\"}>`;\n\n if (className) {\n userPrompt += `\\nClasses: ${className}`;\n }\n\n if (textContent) {\n userPrompt += `\\nText: \"${textContent.slice(0, 50)}\"`;\n }\n\n userPrompt += `\\nComponent: ${componentName}`;\n\n if (editHistory && editHistory.length > 0) {\n userPrompt += `\\n\\nRecent edits:\\n`;\n editHistory.slice(-3).forEach((item, idx) => {\n userPrompt += `${idx + 1}. ${item.suggestion} ${\n item.success ? \"✓\" : \"✗\"\n }\\n`;\n });\n } else {\n userPrompt += `\\n\\nNo previous edits.`;\n }\n\n if (lastSuggestion) {\n userPrompt += `\\n\\n**LAST EDIT APPLIED:** \"${lastSuggestion}\"`;\n userPrompt += `\\n\\nGenerate 6-8 follow-up suggestions (mostly variations of the last edit):`;\n } else {\n userPrompt += `\\n\\nGenerate 6-8 initial suggestions:`;\n }\n\n try {\n const response = await model.invoke([\n new SystemMessage(systemPrompt),\n new HumanMessage(userPrompt),\n ]);\n\n let content =\n typeof response.content === \"string\"\n ? response.content\n : String(response.content);\n\n // Clean up response\n content = content.trim();\n\n // Remove markdown fences if present\n content = content.replace(/^```json?\\s*/gm, \"\").replace(/\\s*```$/gm, \"\");\n\n // Try to parse JSON\n const suggestions = JSON.parse(content);\n\n if (Array.isArray(suggestions)) {\n // Filter and validate suggestions (2-15 words each)\n const validSuggestions = suggestions\n .filter((s) => typeof s === \"string\")\n .map((s) => s.trim())\n .filter((s) => {\n const words = s.split(/\\s+/).length;\n return words >= 1 && words <= 15;\n })\n .slice(0, 8); // Ensure max 8\n\n if (validSuggestions.length >= 4) {\n return validSuggestions;\n }\n }\n\n // Couldn't parse or invalid format\n return null;\n } catch (e) {\n // AI call failed or response parsing failed\n return null;\n }\n}\n","import {\n unstable_v2_createSession,\n unstable_v2_resumeSession,\n type SDKSession,\n type SDKSessionOptions,\n type SDKMessage,\n} from \"@anthropic-ai/claude-agent-sdk\";\n\n/**\n * Configuration for the AI editor agent\n */\nexport interface AIEditorAgentConfig {\n apiKey: string;\n projectRoot: string;\n sessionId?: string; // For resuming sessions\n allowedTools?: string[];\n disallowedTools?: string[];\n}\n\n/**\n * Context about the selected component (optional)\n */\nexport interface ComponentContext {\n filePath: string;\n lineNumber: number;\n componentName: string;\n elementContext?: {\n tagName?: string;\n className?: string;\n textContent?: string;\n [key: string]: any;\n };\n}\n\n/**\n * Wrapper around Claude Agent SDK for the AI editor\n */\nexport class AIEditorAgent {\n private session: SDKSession;\n private projectRoot: string;\n\n private constructor(session: SDKSession, projectRoot: string) {\n this.session = session;\n this.projectRoot = projectRoot;\n }\n\n /**\n * Create a new agent instance\n */\n static async create(config: AIEditorAgentConfig): Promise<AIEditorAgent> {\n const sessionOptions: SDKSessionOptions = {\n model: \"claude-sonnet-4-5-20250929\",\n // Enable auto-apply for edits without permission prompts\n permissionMode: \"acceptEdits\",\n env: {\n ...process.env,\n ANTHROPIC_API_KEY: config.apiKey,\n // Set working directory\n PWD: config.projectRoot,\n },\n // Explicitly allow core development tools\n allowedTools: config.allowedTools || [\"Read\", \"Edit\", \"Glob\", \"Grep\"],\n disallowedTools: config.disallowedTools || [],\n };\n\n let session: SDKSession;\n if (config.sessionId) {\n // Resume existing session\n session = unstable_v2_resumeSession(config.sessionId, sessionOptions);\n } else {\n // Create new session\n session = unstable_v2_createSession(sessionOptions);\n }\n\n return new AIEditorAgent(session, config.projectRoot);\n }\n\n /**\n * Send a message to the agent and stream responses\n */\n async *sendMessage(\n message: string,\n componentContext?: ComponentContext\n ): AsyncGenerator<SDKMessage, void, unknown> {\n // Build the full message with terse response instructions\n let fullMessage = `<response_style>\nKEEP RESPONSES EXTREMELY BRIEF AND STATUS-LIKE.\n- Use terse status messages: \"Reading file.tsx\", \"Changing color\", \"Done\"\n- NO conversational language (avoid: \"I'll\", \"Let me\", \"Sure\", \"Great\", \"I can see\")\n- NO explanations unless explicitly asked\n- State ONLY what you're doing, nothing more\n- Format: Action + target (e.g., \"Updating StatsCard.tsx:24\")\n</response_style>\n\n`;\n\n // If component context is provided, add it to the message\n if (componentContext) {\n fullMessage += `[Component: ${componentContext.componentName} at ${componentContext.filePath}:${componentContext.lineNumber}]\\n\\n`;\n }\n\n fullMessage += message;\n\n // Send the message\n await this.session.send(fullMessage);\n\n // Stream responses\n for await (const event of this.session.stream()) {\n yield event;\n }\n }\n\n /**\n * Get the session ID\n */\n getSessionId(): string {\n return this.session.sessionId;\n }\n\n /**\n * Close the session\n */\n close(): void {\n this.session.close();\n }\n\n /**\n * Async disposal support\n */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.session[Symbol.asyncDispose]();\n }\n}\n","import { AIEditorAgent, type AIEditorAgentConfig } from \"./sdk-client.js\";\n\n/**\n * Represents an active agent session\n */\nexport interface AgentSession {\n sessionId: string;\n threadId: string;\n agent: AIEditorAgent;\n createdAt: number;\n lastActive: number;\n isLocked: boolean;\n}\n\n/**\n * Configuration for creating a new session\n */\nexport interface CreateSessionConfig {\n sessionId?: string; // If provided, resume existing session\n threadId: string;\n apiKey: string;\n projectRoot: string;\n allowedTools?: string[];\n disallowedTools?: string[];\n}\n\n/**\n * Manages agent sessions across requests\n * Sessions are stored in-memory and automatically cleaned up after inactivity\n */\nexport class AgentSessionStore {\n private sessions: Map<string, AgentSession> = new Map();\n private readonly SESSION_TIMEOUT = 1000 * 60 * 30; // 30 minutes\n private readonly CLEANUP_INTERVAL = 1000 * 60 * 5; // 5 minutes\n\n constructor() {\n // Start periodic cleanup of expired sessions\n this.startCleanupTimer();\n }\n\n /**\n * Create or resume a session\n */\n async createSession(config: CreateSessionConfig): Promise<AgentSession> {\n const sessionId = config.sessionId || this.generateSessionId();\n\n // Check if session already exists\n const existing = this.sessions.get(sessionId);\n if (existing) {\n // Update last active time and return existing session\n existing.lastActive = Date.now();\n existing.threadId = config.threadId; // Allow switching threads\n return existing;\n }\n\n // Create new agent instance\n const agent = await AIEditorAgent.create({\n apiKey: config.apiKey,\n projectRoot: config.projectRoot,\n sessionId: config.sessionId,\n allowedTools: config.allowedTools,\n disallowedTools: config.disallowedTools,\n });\n\n // Create session record\n // Note: We use our own sessionId here because the SDK sessionId\n // is not available until after the first message is sent\n const session: AgentSession = {\n sessionId: sessionId,\n threadId: config.threadId,\n agent,\n createdAt: Date.now(),\n lastActive: Date.now(),\n isLocked: false,\n };\n\n this.sessions.set(sessionId, session);\n return session;\n }\n\n /**\n * Get a session by ID\n */\n getSession(sessionId: string): AgentSession | undefined {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.lastActive = Date.now();\n }\n return session;\n }\n\n /**\n * Acquire a lock on a session to prevent concurrent edits\n * Returns true if lock was acquired, false if already locked\n */\n acquireLock(sessionId: string): boolean {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session ${sessionId} not found`);\n }\n\n if (session.isLocked) {\n return false;\n }\n\n session.isLocked = true;\n session.lastActive = Date.now();\n return true;\n }\n\n /**\n * Release a lock on a session\n */\n releaseLock(sessionId: string): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.isLocked = false;\n session.lastActive = Date.now();\n }\n }\n\n /**\n * Check if any session is currently locked (to prevent concurrent edits)\n */\n hasActiveLock(): boolean {\n for (const session of this.sessions.values()) {\n if (session.isLocked) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Get all active sessions for a thread\n */\n getSessionsByThread(threadId: string): AgentSession[] {\n const sessions: AgentSession[] = [];\n for (const session of this.sessions.values()) {\n if (session.threadId === threadId) {\n sessions.push(session);\n }\n }\n return sessions;\n }\n\n /**\n * Delete a session\n */\n deleteSession(sessionId: string): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.agent.close();\n this.sessions.delete(sessionId);\n }\n }\n\n /**\n * Delete all sessions for a thread\n */\n deleteSessionsByThread(threadId: string): void {\n for (const [sessionId, session] of this.sessions.entries()) {\n if (session.threadId === threadId) {\n session.agent.close();\n this.sessions.delete(sessionId);\n }\n }\n }\n\n /**\n * Get all active sessions\n */\n getAllSessions(): AgentSession[] {\n return Array.from(this.sessions.values());\n }\n\n /**\n * Clean up expired sessions\n */\n private cleanupExpiredSessions(): void {\n const now = Date.now();\n const expiredSessions: string[] = [];\n\n for (const [sessionId, session] of this.sessions.entries()) {\n const inactiveTime = now - session.lastActive;\n if (inactiveTime > this.SESSION_TIMEOUT && !session.isLocked) {\n expiredSessions.push(sessionId);\n }\n }\n\n for (const sessionId of expiredSessions) {\n console.log(\n `[AgentSessionStore] Cleaning up expired session: ${sessionId}`\n );\n this.deleteSession(sessionId);\n }\n\n if (expiredSessions.length > 0) {\n console.log(\n `[AgentSessionStore] Cleaned up ${expiredSessions.length} expired sessions`\n );\n }\n }\n\n /**\n * Start periodic cleanup timer\n */\n private startCleanupTimer(): void {\n setInterval(() => {\n this.cleanupExpiredSessions();\n }, this.CLEANUP_INTERVAL);\n }\n\n /**\n * Generate a unique session ID\n */\n private generateSessionId(): string {\n return `session-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n }\n\n /**\n * Get statistics about the session store\n */\n getStats() {\n return {\n totalSessions: this.sessions.size,\n lockedSessions: Array.from(this.sessions.values()).filter(\n (s) => s.isLocked\n ).length,\n sessions: Array.from(this.sessions.values()).map((s) => ({\n sessionId: s.sessionId,\n threadId: s.threadId,\n isLocked: s.isLocked,\n ageMinutes: Math.floor((Date.now() - s.createdAt) / 1000 / 60),\n inactiveMinutes: Math.floor((Date.now() - s.lastActive) / 1000 / 60),\n })),\n };\n }\n}\n\n// Singleton instance\nlet sessionStore: AgentSessionStore | null = null;\n\n/**\n * Get the global session store instance\n */\nexport function getSessionStore(): AgentSessionStore {\n if (!sessionStore) {\n sessionStore = new AgentSessionStore();\n }\n return sessionStore;\n}\n","// =============================================================================\n// FILE: src/server/handlers/chat.ts\n// SSE streaming endpoint for AI chat using Agent SDK\n// =============================================================================\n\nimport { NextRequest, NextResponse } from \"next/server\";\nimport { validateDevMode } from \"../utils/file-system.js\";\nimport { getSessionStore } from \"../agent/session-store.js\";\nimport type { ComponentContext } from \"../agent/sdk-client.js\";\n\ninterface ChatRequest {\n sessionId?: string;\n threadId: string;\n message: string;\n componentContext?: ComponentContext;\n}\n\n/**\n * Handle chat requests with SSE streaming\n */\nexport async function handleChat(req: NextRequest): Promise<Response> {\n const devModeError = validateDevMode();\n if (devModeError) return devModeError;\n\n try {\n const body: ChatRequest = await req.json();\n const { sessionId, threadId, message, componentContext } = body;\n\n // Validate request\n if (!threadId || !message) {\n return NextResponse.json(\n { error: \"threadId and message are required\" },\n { status: 400 }\n );\n }\n\n // Get API key from environment\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n return NextResponse.json(\n { error: \"ANTHROPIC_API_KEY not configured\" },\n { status: 500 }\n );\n }\n\n // Get or create session\n const sessionStore = getSessionStore();\n const projectRoot = process.cwd();\n\n const session = await sessionStore.createSession({\n sessionId,\n threadId,\n apiKey,\n projectRoot,\n });\n\n // Try to acquire lock\n if (!sessionStore.acquireLock(session.sessionId)) {\n return NextResponse.json(\n {\n error:\n \"Another operation is in progress. Please wait for it to complete.\",\n },\n { status: 409 }\n );\n }\n\n // Create SSE stream\n const encoder = new TextEncoder();\n const stream = new ReadableStream({\n async start(controller) {\n try {\n // Send initial event\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ type: \"connected\", sessionId: session.sessionId })}\\n\\n`\n )\n );\n\n // Stream agent responses\n for await (const event of session.agent.sendMessage(\n message,\n componentContext\n )) {\n // Log all events for debugging\n console.log(\"[AGENT EVENT]\", event.type, JSON.stringify(event, null, 2));\n\n // Send event to client\n controller.enqueue(\n encoder.encode(`data: ${JSON.stringify(event)}\\n\\n`)\n );\n }\n\n // Send completion event\n controller.enqueue(\n encoder.encode(`data: ${JSON.stringify({ type: \"done\" })}\\n\\n`)\n );\n\n controller.close();\n } catch (error: any) {\n console.error(\"[handleChat] Error:\", error);\n\n // Send error event\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ type: \"error\", error: error.message || String(error) })}\\n\\n`\n )\n );\n\n controller.close();\n } finally {\n // Release lock\n sessionStore.releaseLock(session.sessionId);\n }\n },\n });\n\n // Return SSE response\n return new Response(stream, {\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n },\n });\n } catch (error) {\n console.error(\"[handleChat] Request error:\", error);\n return NextResponse.json(\n { 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\";\nimport { handleSuggestions } from \"./suggestions\";\nimport { handleChat } from \"./chat\";\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 * - GET /api/ai-editor/suggestions -> handleSuggestions\n * - POST /api/ai-editor/chat -> handleChat (SSE)\n */\nexport async function handleAIEditorRequest(\n req: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n): Promise<NextResponse | Response> {\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 case \"suggestions\":\n if (method === \"GET\") return handleSuggestions(req);\n break;\n case \"chat\":\n if (method === \"POST\") return handleChat(req);\n break;\n }\n\n return NextResponse.json(\n { error: `Unknown endpoint: ${endpoint}` },\n { status: 404 }\n );\n}\n","/**\n * Comment persistence handler\n * Saves/loads comments to/from .ai-editor/comments.json\n */\n\nimport { NextRequest, NextResponse } from \"next/server\";\nimport { readFile, writeFile, mkdir } from \"fs/promises\";\nimport { join } from \"path\";\nimport { existsSync } from \"fs\";\n\nconst STORAGE_DIR = \".ai-editor\";\nconst STORAGE_FILE = \"comments.json\";\n\n/**\n * Get the project root directory\n */\nfunction getProjectRoot(): string {\n return process.cwd();\n}\n\n/**\n * Get the comments storage path\n */\nfunction getStoragePath(): string {\n return join(getProjectRoot(), STORAGE_DIR, STORAGE_FILE);\n}\n\n/**\n * Ensure storage directory exists\n */\nasync function ensureStorageDir(): Promise<void> {\n const dir = join(getProjectRoot(), STORAGE_DIR);\n if (!existsSync(dir)) {\n await mkdir(dir, { recursive: true });\n }\n}\n\n/**\n * Handle comment persistence requests\n */\nexport async function handleCommentsRequest(\n request: NextRequest\n): Promise<NextResponse> {\n // Only allow in development mode\n if (process.env.NODE_ENV !== \"development\") {\n return NextResponse.json(\n { error: \"Comments API only available in development\" },\n { status: 403 }\n );\n }\n\n try {\n if (request.method === \"GET\") {\n // Load comments\n const storagePath = getStoragePath();\n\n if (!existsSync(storagePath)) {\n return NextResponse.json({ comments: [] });\n }\n\n const data = await readFile(storagePath, \"utf-8\");\n const comments = JSON.parse(data);\n\n return NextResponse.json({ comments });\n }\n\n if (request.method === \"POST\") {\n const body = await request.json();\n const { action } = body;\n\n if (action === \"save\") {\n // Save comments\n const { comments } = body;\n\n await ensureStorageDir();\n const storagePath = getStoragePath();\n\n await writeFile(storagePath, JSON.stringify(comments, null, 2), \"utf-8\");\n\n return NextResponse.json({ success: true });\n }\n\n if (action === \"clear\") {\n // Clear comments\n await ensureStorageDir();\n const storagePath = getStoragePath();\n\n await writeFile(storagePath, JSON.stringify([]), \"utf-8\");\n\n return NextResponse.json({ success: true });\n }\n\n return NextResponse.json(\n { error: \"Invalid action\" },\n { status: 400 }\n );\n }\n\n return NextResponse.json(\n { error: \"Method not allowed\" },\n { status: 405 }\n );\n } catch (error) {\n console.error(\"Comment storage error:\", error);\n return NextResponse.json(\n { error: \"Internal server error\" },\n { status: 500 }\n );\n }\n}\n"],"names":["NextResponse","fileExists","parser","path","t","ChatAnthropic","SystemMessage","HumanMessage","marker","cleanPath","shouldSkipPath","sourceMap","consumer","SourceMapConsumer","normalizeSourcePath","nthOfType","key","unstable_v2_resumeSession","unstable_v2_createSession","sessionStore","join","existsSync","mkdir","readFile","writeFile"],"mappings":"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"}
|