Skip to content

Commit f331b0a

Browse files
added file tree & fixed error logs
1 parent 3535eff commit f331b0a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1109
-7990
lines changed

app/api/ai/analyze-code/route.ts

Lines changed: 25 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { NextRequest, NextResponse } from 'next/server'
2-
import { supabase } from '@/lib/supabase'
32

43
interface CodeAnalysisRequest {
54
code: string
65
language: string
76
file: string
87
cursorPosition: { line: number; column: number }
8+
model: any // LLMModel
9+
config: any
910
}
1011

1112
interface CodeSuggestion {
@@ -30,6 +31,7 @@ interface Diagnostic {
3031

3132
export async function POST(request: NextRequest) {
3233
try {
34+
const supabase = require('@/lib/supabase').supabase
3335
const authHeader = request.headers.get('authorization')
3436
if (!authHeader) {
3537
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
@@ -42,14 +44,14 @@ export async function POST(request: NextRequest) {
4244
}
4345

4446
const body: CodeAnalysisRequest = await request.json()
45-
const { code, language, file, cursorPosition } = body
47+
const { code, language, file, cursorPosition, model, config } = body
4648

47-
if (!code || !language) {
49+
if (!code || !language || !model || !config) {
4850
return NextResponse.json({ error: 'Missing required fields' }, { status: 400 })
4951
}
5052

5153
// Analyze code using AI
52-
const analysis = await analyzeCodeWithAI(code, language, file, cursorPosition)
54+
const analysis = await analyzeCodeWithAI(code, language, file, cursorPosition, model, config)
5355

5456
return NextResponse.json({
5557
suggestions: analysis.suggestions,
@@ -70,109 +72,44 @@ async function analyzeCodeWithAI(
7072
code: string,
7173
language: string,
7274
file: string,
73-
cursorPosition: { line: number; column: number }
75+
cursorPosition: { line: number; column: number },
76+
model: any, // LLMModel
77+
config: any // LLMModelConfig
7478
): Promise<{
7579
suggestions: CodeSuggestion[]
7680
diagnostics: Diagnostic[]
7781
metrics: any
7882
}> {
79-
// Get OpenAI API key from environment
80-
const apiKey = process.env.OPENAI_API_KEY
81-
if (!apiKey) {
82-
throw new Error('OpenAI API key not configured')
83-
}
84-
8583
const lines = code.split('\n')
8684
const currentLine = lines[cursorPosition.line - 1] || ''
87-
const context = lines.slice(Math.max(0, cursorPosition.line - 5), cursorPosition.line + 5).join('\n')
8885

8986
try {
90-
const response = await fetch('https://api.openai.com/v1/chat/completions', {
91-
method: 'POST',
92-
headers: {
93-
'Authorization': `Bearer ${apiKey}`,
94-
'Content-Type': 'application/json',
95-
},
96-
body: JSON.stringify({
97-
model: 'gpt-4',
98-
messages: [
99-
{
100-
role: 'system',
101-
content: `You are an expert code analyst and assistant. Analyze the provided ${language} code and provide:
102-
103-
1. **Code Suggestions**: Improvements, optimizations, refactoring opportunities
104-
2. **Diagnostics**: Potential errors, warnings, and issues
105-
3. **Best Practices**: Adherence to ${language} conventions and patterns
106-
107-
Focus on:
108-
- Performance optimizations
109-
- Code quality improvements
110-
- Security vulnerabilities
111-
- Best practice violations
112-
- Type safety (for TypeScript)
113-
- Modern syntax usage
114-
- Error handling improvements
115-
116-
Return your analysis as JSON in this exact format:
117-
{
118-
"suggestions": [
119-
{
120-
"id": "unique-id",
121-
"type": "completion|refactor|fix|optimize",
122-
"line": number,
123-
"column": number,
124-
"text": "original text",
125-
"replacement": "suggested replacement",
126-
"confidence": 0.0-1.0,
127-
"description": "brief description"
128-
}
129-
],
130-
"diagnostics": [
131-
{
132-
"id": "unique-id",
133-
"type": "error|warning|info",
134-
"line": number,
135-
"column": number,
136-
"message": "diagnostic message",
137-
"suggestion": "optional fix suggestion"
138-
}
139-
]
140-
}`
141-
},
142-
{
143-
role: 'user',
144-
content: `Analyze this ${language} code from file "${file}":
145-
146-
\`\`\`${language}
147-
${code}
148-
\`\`\`
149-
150-
Current cursor position: Line ${cursorPosition.line}, Column ${cursorPosition.column}
151-
Current line context: "${currentLine}"
152-
153-
Provide analysis focusing on the area around the cursor and overall code quality.`
154-
}
155-
],
156-
temperature: 0.3,
157-
max_tokens: 2000,
158-
}),
87+
const { E2BToolClient, E2BToolType } = require('@/lib/e2b/toolClient')
88+
const e2bToolClient = new E2BToolClient()
89+
90+
const result = await e2bToolClient.execute({
91+
toolType: 'new_task' as any, //E2BToolType,
92+
userInput: `Analyze this ${language} code from file "${file}":\n\`\`\`${language}\n${code}\n\`\`\`\nCurrent cursor position: Line ${cursorPosition.line}, Column ${cursorPosition.column}\nCurrent line context: "${currentLine}"\n\nProvide analysis focusing on the area around the cursor and overall code quality.`,
93+
model: model,
94+
config: config,
95+
userID: 'user-id', // Replace with actual user ID
96+
teamID: 'team-id', // Replace with actual team ID
15997
})
16098

161-
if (!response.ok) {
162-
throw new Error(`OpenAI API error: ${response.statusText}`)
99+
if (!result.success) {
100+
throw new Error(result.executionResult.toolResponse || 'Code analysis failed')
163101
}
164102

165-
const result = await response.json()
166-
const analysisText = result.choices[0]?.message?.content
103+
const analysisText = result.executionResult.aiResponse
167104

168105
if (!analysisText) {
169-
throw new Error('No analysis returned from OpenAI')
106+
throw new Error('No analysis returned from AI')
170107
}
171108

172109
// Parse the JSON response
173110
try {
174111
const analysis = JSON.parse(analysisText)
175-
112+
176113
// Add IDs if missing
177114
analysis.suggestions = analysis.suggestions?.map((s: any, i: number) => ({
178115
...s,
@@ -236,4 +173,4 @@ function calculateComplexity(code: string): number {
236173
}
237174

238175
return complexity
239-
}
176+
}

app/api/ai/generate-file/route.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
import fs from 'fs';
3+
import path from 'path';
4+
5+
const projectRoot = process.cwd();
6+
7+
export async function POST(request: NextRequest) {
8+
try {
9+
const { path: newPath, prompt } = await request.json();
10+
const fullPath = path.join(projectRoot, newPath);
11+
12+
// This is where you would call your AI model to generate the file content
13+
// For now, we'll just use the prompt as the content
14+
const content = `// content for ${newPath}\n\n${prompt}`;
15+
16+
fs.writeFileSync(fullPath, content);
17+
18+
return NextResponse.json({ success: true });
19+
} catch (error) {
20+
console.error('Failed to generate file:', error);
21+
return NextResponse.json(
22+
{ error: 'Failed to generate file' },
23+
{ status: 500 }
24+
);
25+
}
26+
}

app/api/file-system/route.ts

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
import fs from 'fs';
3+
import path from 'path';
4+
5+
type FileSystemNode = {
6+
id: string;
7+
name: string;
8+
type: 'file' | 'folder';
9+
path: string;
10+
children?: FileSystemNode[];
11+
};
12+
13+
const projectRoot = process.cwd();
14+
15+
function getFileTree(dir: string): FileSystemNode[] {
16+
const dirents = fs.readdirSync(dir, { withFileTypes: true });
17+
const tree: FileSystemNode[] = [];
18+
19+
for (const dirent of dirents) {
20+
const fullPath = path.join(dir, dirent.name);
21+
const id = path.relative(projectRoot, fullPath);
22+
23+
if (dirent.isDirectory()) {
24+
tree.push({
25+
id,
26+
name: dirent.name,
27+
type: 'folder',
28+
path: id,
29+
children: getFileTree(fullPath),
30+
});
31+
} else {
32+
tree.push({
33+
id,
34+
name: dirent.name,
35+
type: 'file',
36+
path: id,
37+
});
38+
}
39+
}
40+
return tree;
41+
}
42+
43+
export async function GET(request: NextRequest) {
44+
try {
45+
const fileTree = getFileTree(projectRoot);
46+
return NextResponse.json(fileTree);
47+
} catch (error) {
48+
console.error('Failed to read file tree:', error);
49+
return NextResponse.json(
50+
{ error: 'Failed to read file tree' },
51+
{ status: 500 }
52+
);
53+
}
54+
}
55+
56+
export async function POST(request: NextRequest) {
57+
try {
58+
const { path: newPath, type } = await request.json();
59+
const fullPath = path.join(projectRoot, newPath);
60+
61+
if (type === 'folder') {
62+
fs.mkdirSync(fullPath, { recursive: true });
63+
} else {
64+
fs.writeFileSync(fullPath, '');
65+
}
66+
67+
return NextResponse.json({ success: true });
68+
} catch (error) {
69+
console.error('Failed to create file/folder:', error);
70+
return NextResponse.json(
71+
{ error: 'Failed to create file/folder' },
72+
{ status: 500 }
73+
);
74+
}
75+
}
76+
77+
export async function PUT(request: NextRequest) {
78+
try {
79+
const { oldPath, newPath } = await request.json();
80+
const fullOldPath = path.join(projectRoot, oldPath);
81+
const fullNewPath = path.join(projectRoot, newPath);
82+
83+
fs.renameSync(fullOldPath, fullNewPath);
84+
85+
return NextResponse.json({ success: true });
86+
} catch (error) {
87+
console.error('Failed to rename file/folder:', error);
88+
return NextResponse.json(
89+
{ error: 'Failed to rename file/folder' },
90+
{ status: 500 }
91+
);
92+
}
93+
}
94+
95+
export async function DELETE(request: NextRequest) {
96+
try {
97+
const { path: deletePath } = await request.json();
98+
const fullPath = path.join(projectRoot, deletePath);
99+
100+
const stat = fs.statSync(fullPath);
101+
if (stat.isDirectory()) {
102+
fs.rmdirSync(fullPath, { recursive: true });
103+
} else {
104+
fs.unlinkSync(fullPath);
105+
}
106+
107+
return NextResponse.json({ success: true });
108+
} catch (error) {
109+
console.error('Failed to delete file/folder:', error);
110+
return NextResponse.json(
111+
{ error: 'Failed to delete file/folder' },
112+
{ status: 500 }
113+
);
114+
}
115+
}

app/api/sandbox/route.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,25 +201,30 @@ export async function POST(req: Request) {
201201

202202
function validateSandboxRequest(request: any): { valid: boolean; error?: string; code?: string } {
203203
if (!request.fragment) {
204+
console.error("Validation failed: Fragment is required", { code: "MISSING_FRAGMENT" }); // Added logging
204205
return { valid: false, error: "Fragment is required", code: "MISSING_FRAGMENT" }
205206
}
206207

207208
if (!request.userID || typeof request.userID !== 'string') {
209+
console.error("Validation failed: Valid user ID is required", { code: "MISSING_USER_ID", userID: request.userID }); // Added logging
208210
return { valid: false, error: "Valid user ID is required", code: "MISSING_USER_ID" }
209211
}
210212

211213
if (!request.teamID || typeof request.teamID !== 'string') {
214+
console.error("Validation failed: Valid team ID is required", { code: "MISSING_TEAM_ID", teamID: request.teamID }); // Added logging
212215
return { valid: false, error: "Valid team ID is required", code: "MISSING_TEAM_ID" }
213216
}
214217

215218
const { fragment } = request
216219

217220
if (!fragment.template || typeof fragment.template !== 'string') {
221+
console.error("Validation failed: Valid template is required", { code: "INVALID_TEMPLATE", template: fragment.template }); // Added logging
218222
return { valid: false, error: "Valid template is required", code: "INVALID_TEMPLATE" }
219223
}
220224

221225

222226
if (!Object.keys(templatesData).includes(fragment.template)) {
227+
console.error("Validation failed: Unknown template", { code: "UNKNOWN_TEMPLATE", template: fragment.template, allowedTemplates: Object.keys(templatesData) }); // Added logging
223228
return { valid: false, error: `Template '${fragment.template}' is not a valid template.`, code: "UNKNOWN_TEMPLATE" }
224229
}
225230

@@ -228,9 +233,11 @@ function validateSandboxRequest(request: any): { valid: boolean; error?: string;
228233
for (let i = 0; i < fragment.files.length; i++) {
229234
const file = fragment.files[i]
230235
if (!file.file_path || typeof file.file_path !== 'string') {
236+
console.error("Validation failed: File missing or invalid file path", { code: "INVALID_FILE_PATH", fileIndex: i, filePath: file.file_path }); // Added logging
231237
return { valid: false, error: `File ${i}: Missing or invalid file path`, code: "INVALID_FILE_PATH" }
232238
}
233239
if (typeof file.file_content !== 'string') {
240+
console.error("Validation failed: File content must be a string", { code: "INVALID_FILE_CONTENT", fileIndex: i }); // Added logging
234241
return { valid: false, error: `File ${i}: File content must be a string`, code: "INVALID_FILE_CONTENT" }
235242
}
236243
}

0 commit comments

Comments
 (0)