Skip to content

Commit 4027830

Browse files
fixed overlapping file views
1 parent d2ab971 commit 4027830

16 files changed

Lines changed: 2807 additions & 529 deletions

app/api/chat/route.ts

Lines changed: 115 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
// app/api/chat/route.ts - Enhanced with better error handling and project analysis
12
import type { Duration } from "@/lib/duration"
23
import type { LLMModel, LLMModelConfig } from "@/lib/models"
34
import { getModelClient } from "@/lib/models"
4-
import { toPrompt } from "@/lib/prompt"
5+
import { toEnhancedPrompt } from "@/lib/enhanced-prompt"
56
import ratelimit from "@/lib/ratelimit"
67
import { fragmentSchema as schema } from "@/lib/schema"
78
import type { TemplatesDataObject } from "@/lib/templates"
9+
import { ProjectAnalyzer, type ProjectStructure } from "@/lib/project-analyzer"
810
import { streamObject, type LanguageModel, type CoreMessage } from "ai"
11+
import { logError, generateRequestId, validateRequestData } from "@/lib/debug"
912

1013
export const maxDuration = 60
1114

@@ -15,18 +18,18 @@ const rateLimitMaxRequests = process.env.RATE_LIMIT_MAX_REQUESTS
1518
const ratelimitWindow = process.env.RATE_LIMIT_WINDOW ? (process.env.RATE_LIMIT_WINDOW as Duration) : "1d"
1619

1720
export async function POST(req: Request) {
18-
const requestId = `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
21+
const requestId = generateRequestId()
1922

2023
try {
21-
console.log(`[Chat API ${requestId}] Processing request`)
24+
console.log(`[Enhanced Chat API ${requestId}] Processing request`)
2225

23-
// Parse request body with error handling
26+
// Parse request body with enhanced error handling
2427
let body: any
2528
try {
2629
body = await req.json()
27-
console.log(`[Chat API ${requestId}] Request body parsed, keys:`, Object.keys(body))
30+
console.log(`[Enhanced Chat API ${requestId}] Request body parsed, keys:`, Object.keys(body))
2831
} catch (error) {
29-
console.error(`[Chat API ${requestId}] Request body parsing failed:`, error)
32+
logError("Request body parsing", error, { requestId })
3033
return new Response(
3134
JSON.stringify({
3235
error: "Invalid JSON in request body",
@@ -47,84 +50,28 @@ export async function POST(req: Request) {
4750
template,
4851
model,
4952
config,
53+
uploadedFiles, // New: support for uploaded files
54+
analysisInstructions, // New: specific instructions for analysis
5055
}: {
5156
messages: CoreMessage[]
5257
userID: string
5358
teamID: string
5459
template: TemplatesDataObject
5560
model: LLMModel
5661
config: LLMModelConfig
62+
uploadedFiles?: File[]
63+
analysisInstructions?: string
5764
} = body
5865

59-
// Enhanced validation with specific error messages
60-
if (!userID || !teamID) {
61-
console.error(`[Chat API ${requestId}] Missing authentication:`, {
62-
hasUserID: !!userID,
63-
hasTeamID: !!teamID,
64-
userID: userID?.substring(0, 8) + "...",
65-
teamID: teamID?.substring(0, 8) + "...",
66-
})
67-
68-
return new Response(
69-
JSON.stringify({
70-
error: "Authentication required. Please ensure you're signed in and have a valid team.",
71-
code: "MISSING_AUTH",
72-
details: {
73-
missingUserID: !userID,
74-
missingTeamID: !teamID,
75-
},
76-
requestId,
77-
}),
78-
{
79-
status: 401,
80-
headers: { "Content-Type": "application/json" },
81-
},
82-
)
83-
}
84-
85-
if (!messages || !Array.isArray(messages) || messages.length === 0) {
86-
console.error(`[Chat API ${requestId}] Invalid messages:`, {
87-
hasMessages: !!messages,
88-
isArray: Array.isArray(messages),
89-
length: messages?.length,
90-
})
91-
92-
return new Response(
93-
JSON.stringify({
94-
error: "Messages are required and must be a non-empty array",
95-
code: "INVALID_MESSAGES",
96-
requestId,
97-
}),
98-
{
99-
status: 400,
100-
headers: { "Content-Type": "application/json" },
101-
},
102-
)
103-
}
104-
105-
if (!model || !model.id || !model.providerId) {
106-
console.error(`[Chat API ${requestId}] Invalid model:`, model)
107-
108-
return new Response(
109-
JSON.stringify({
110-
error: "Valid model configuration is required",
111-
code: "INVALID_MODEL",
112-
requestId,
113-
}),
114-
{
115-
status: 400,
116-
headers: { "Content-Type": "application/json" },
117-
},
118-
)
119-
}
120-
121-
if (!template) {
122-
console.error(`[Chat API ${requestId}] Invalid template:`, template)
123-
66+
// Enhanced validation with better error messages
67+
const validation = validateRequestData(body)
68+
if (!validation.valid) {
69+
logError("Request validation failed", new Error(validation.errors.join(", ")), { requestId, errors: validation.errors })
12470
return new Response(
12571
JSON.stringify({
126-
error: "Template configuration is required",
127-
code: "INVALID_TEMPLATE",
72+
error: "Request validation failed",
73+
code: "VALIDATION_ERROR",
74+
details: validation.errors,
12875
requestId,
12976
}),
13077
{
@@ -134,22 +81,44 @@ export async function POST(req: Request) {
13481
)
13582
}
13683

137-
console.log(`[Chat API ${requestId}] Validation passed:`, {
84+
console.log(`[Enhanced Chat API ${requestId}] Validation passed:`, {
13885
userID: userID.substring(0, 8) + "...",
13986
teamID: teamID.substring(0, 8) + "...",
14087
modelId: model.id,
14188
provider: model.providerId,
14289
messagesCount: messages.length,
90+
hasUploadedFiles: !!(uploadedFiles && uploadedFiles.length > 0),
14391
})
14492

93+
// Analyze uploaded files if present
94+
let projectStructure: ProjectStructure | undefined
95+
if (uploadedFiles && uploadedFiles.length > 0) {
96+
try {
97+
console.log(`[Enhanced Chat API ${requestId}] Analyzing ${uploadedFiles.length} uploaded files`)
98+
const analyzer = new ProjectAnalyzer()
99+
const analysis = await analyzer.analyzeProject(uploadedFiles)
100+
projectStructure = analysis.structure
101+
102+
console.log(`[Enhanced Chat API ${requestId}] Project analysis completed:`, {
103+
filesAnalyzed: uploadedFiles.length,
104+
dependenciesFound: projectStructure.dependencies.size,
105+
componentsFound: projectStructure.components.size,
106+
architectureType: projectStructure.architecture.type,
107+
})
108+
} catch (analysisError) {
109+
logError("Project analysis failed", analysisError, { requestId, filesCount: uploadedFiles.length })
110+
console.warn(`[Enhanced Chat API ${requestId}] Project analysis failed, continuing without analysis:`, analysisError)
111+
}
112+
}
113+
145114
// Rate limiting check
146115
try {
147116
const limit = !config.apiKey
148117
? await ratelimit(req.headers.get("x-forwarded-for"), rateLimitMaxRequests, ratelimitWindow)
149118
: false
150119

151120
if (limit) {
152-
console.log(`[Chat API ${requestId}] Rate limit hit:`, limit)
121+
console.log(`[Enhanced Chat API ${requestId}] Rate limit hit:`, limit)
153122
return new Response(
154123
JSON.stringify({
155124
error: "You have reached your request limit for the day.",
@@ -168,24 +137,24 @@ export async function POST(req: Request) {
168137
},
169138
)
170139
}
171-
console.log(`[Chat API ${requestId}] Rate limit check passed`)
140+
console.log(`[Enhanced Chat API ${requestId}] Rate limit check passed`)
172141
} catch (error) {
173-
console.warn(`[Chat API ${requestId}] Rate limiting check failed:`, error)
142+
logError("Rate limiting check failed", error, { requestId })
174143
// Continue without rate limiting if it fails
175144
}
176145

177146
// Create model client with enhanced error handling
178147
let modelClient: LanguageModel
179148
try {
180-
console.log(`[Chat API ${requestId}] Creating model client for:`, model.providerId, model.id)
149+
console.log(`[Enhanced Chat API ${requestId}] Creating model client for:`, model.providerId, model.id)
181150
modelClient = getModelClient(model, config) as LanguageModel
182-
console.log(`[Chat API ${requestId}] Model client created successfully`)
151+
console.log(`[Enhanced Chat API ${requestId}] Model client created successfully`)
183152
} catch (error: any) {
184-
console.error(`[Chat API ${requestId}] Model client creation failed:`, error)
153+
logError("Model client creation failed", error, { requestId, provider: model.providerId, modelId: model.id })
185154

186155
return new Response(
187156
JSON.stringify({
188-
error: `Failed to initialize ${model.providerId} model: ${error.message}`, // Use model.providerId for consistency
157+
error: `Failed to initialize ${model.providerId} model. Please check your API key configuration.`,
189158
code: "MODEL_INIT_ERROR",
190159
provider: model.providerId,
191160
details: error.message,
@@ -198,21 +167,30 @@ export async function POST(req: Request) {
198167
)
199168
}
200169

201-
// Prepare model parameters from config, excluding model and apiKey used for client instantiation
202-
const { model: _modelFromConfig, apiKey: _apiKeyFromConfig, ...providerSpecificConfig } = config
203-
204-
// Clean up undefined values from provider-specific config
205-
const cleanProviderSpecificConfig = Object.fromEntries(
206-
Object.entries(providerSpecificConfig).filter(([_, value]) => value !== undefined),
207-
)
170+
// Extract user prompt from the last message
171+
const lastMessage = messages[messages.length - 1]
172+
let userPrompt = ''
173+
if (Array.isArray(lastMessage?.content)) {
174+
userPrompt = lastMessage.content
175+
.filter((content: any) => content.type === 'text')
176+
.map((content: any) => content.text)
177+
.join(' ')
178+
}
208179

209180
let systemPrompt: string
210181
try {
211-
systemPrompt = toPrompt(template)
212-
// The check for empty systemPrompt with template content was removed due to type mismatch.
213-
// toPrompt is responsible for handling the TemplatesDataObject.
182+
if (projectStructure && userPrompt) {
183+
console.log(`[Enhanced Chat API ${requestId}] Generating enhanced prompt with project context`)
184+
systemPrompt = toEnhancedPrompt(template, userPrompt, projectStructure)
185+
} else {
186+
console.log(`[Enhanced Chat API ${requestId}] Using standard prompt generation`)
187+
// Fallback to existing prompt system
188+
systemPrompt = generateFallbackPrompt(template)
189+
}
190+
191+
console.log(`[Enhanced Chat API ${requestId}] System prompt generated, length:`, systemPrompt.length)
214192
} catch (error: any) {
215-
console.error(`[Chat API ${requestId}] System prompt generation failed:`, error)
193+
logError("System prompt generation failed", error, { requestId })
216194
return new Response(
217195
JSON.stringify({
218196
error: "Failed to generate system prompt from template.",
@@ -227,32 +205,41 @@ export async function POST(req: Request) {
227205
)
228206
}
229207

230-
console.log(`[Chat API ${requestId}] Creating stream with params:`, {
208+
// Prepare model parameters from config
209+
const { model: _modelFromConfig, apiKey: _apiKeyFromConfig, ...providerSpecificConfig } = config
210+
211+
// Clean up undefined values from provider-specific config
212+
const cleanProviderSpecificConfig = Object.fromEntries(
213+
Object.entries(providerSpecificConfig).filter(([_, value]) => value !== undefined),
214+
)
215+
216+
console.log(`[Enhanced Chat API ${requestId}] Creating stream with params:`, {
231217
providerSpecificConfigKeys: Object.keys(cleanProviderSpecificConfig),
232218
systemPromptLength: systemPrompt.length,
219+
hasProjectContext: !!projectStructure,
233220
})
234221

235222
try {
236223
const streamConfig = {
237224
model: modelClient,
238225
schema,
239-
system: systemPrompt, // Use the validated system prompt
226+
system: systemPrompt,
240227
messages,
241-
maxRetries: 1, // Reduce retries to avoid timeout issues
242-
...cleanProviderSpecificConfig, // Pass cleaned provider-specific parameters
228+
maxRetries: 2, // Increase retries for better reliability
229+
...cleanProviderSpecificConfig,
243230
}
244231

245-
console.log(`[Chat API ${requestId}] Starting stream object creation`)
232+
console.log(`[Enhanced Chat API ${requestId}] Starting stream object creation`)
246233
const stream = await streamObject(streamConfig)
247234

248-
console.log(`[Chat API ${requestId}] Stream created successfully`)
235+
console.log(`[Enhanced Chat API ${requestId}] Stream created successfully`)
249236
return stream.toTextStreamResponse()
250237
} catch (error: any) {
251-
console.error(`[Chat API ${requestId}] Stream creation failed:`, {
252-
error: error.message,
253-
stack: error.stack,
254-
status: error.status,
255-
code: error.code,
238+
logError("Stream creation failed", error, {
239+
requestId,
240+
provider: model.providerId,
241+
modelId: model.id,
242+
hasProjectContext: !!projectStructure
256243
})
257244

258245
// Enhanced error categorization
@@ -326,7 +313,7 @@ export async function POST(req: Request) {
326313
if (errorMessage.includes("model") && errorMessage.includes("not found")) {
327314
return new Response(
328315
JSON.stringify({
329-
error: `Model ${model.id} is not available for ${model.providerId}.`, // Use model.providerId
316+
error: `Model ${model.id} is not available for ${model.providerId}.`,
330317
code: "MODEL_NOT_FOUND",
331318
provider: model.providerId,
332319
modelId: model.id,
@@ -363,7 +350,7 @@ export async function POST(req: Request) {
363350
)
364351
}
365352
} catch (error: any) {
366-
console.error(`[Chat API ${requestId}] Request processing failed:`, error)
353+
logError("Request processing failed", error, { requestId })
367354

368355
return new Response(
369356
JSON.stringify({
@@ -379,3 +366,26 @@ export async function POST(req: Request) {
379366
)
380367
}
381368
}
369+
370+
// Fallback prompt generation function
371+
function generateFallbackPrompt(template: TemplatesDataObject): string {
372+
return `You are an expert software engineer with deep knowledge of modern web development, programming languages, frameworks, and best practices.
373+
374+
Generate production-ready code based on the user's requirements using the following templates:
375+
376+
${Object.entries(template).map(([id, t], index) =>
377+
`${index + 1}. ${id}: "${t.instructions}". File: ${t.file || 'none'}. Dependencies: ${t.lib.join(', ')}. Port: ${t.port || 'none'}.`
378+
).join('\n')}
379+
380+
IMPORTANT GUIDELINES:
381+
- Write clean, maintainable, and well-documented code
382+
- Follow modern best practices and patterns
383+
- Include proper error handling and validation
384+
- Ensure code is production-ready
385+
- Use TypeScript when applicable for type safety
386+
- Implement responsive design for web applications
387+
- Follow accessibility guidelines (WCAG 2.1)
388+
- Include proper security measures
389+
390+
Generate complete, functional code that fulfills the user's request.`
391+
}

0 commit comments

Comments
 (0)