Spaces:
Running
Running
refactor: Stream raw AI response and signal type via header
Browse files
server.js
CHANGED
@@ -467,6 +467,13 @@ ONLY output the changes in this format. Do NOT output the full HTML file again.`
|
|
467 |
let completeResponse = "";
|
468 |
|
469 |
try {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
470 |
const chatCompletion = client.chatCompletionStream({
|
471 |
model: MODEL_ID,
|
472 |
provider: "fireworks-ai", // Ensure provider is correct if needed
|
@@ -475,70 +482,27 @@ ONLY output the changes in this format. Do NOT output the full HTML file again.`
|
|
475 |
// temperature: 0.7, // Adjust temperature if needed
|
476 |
});
|
477 |
|
478 |
-
// ---
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
}
|
486 |
-
// Optional: Add a timeout or check response length to prevent infinite loops
|
487 |
-
if (completeResponse.length > 50000) { // Example limit
|
488 |
-
console.error("AI response exceeded length limit during accumulation.");
|
489 |
-
throw new Error("AI response too long during accumulation.");
|
490 |
-
}
|
491 |
-
}
|
492 |
-
|
493 |
-
// Check if the response seems truncated (didn't finish properly)
|
494 |
-
// This is heuristic - might need refinement
|
495 |
-
if (!chatCompletion?.controller?.signal?.aborted && !completeResponse.trim()) {
|
496 |
-
console.warn("AI stream finished but response is empty.");
|
497 |
-
// Return original HTML as maybe no changes were needed or AI failed silently.
|
498 |
-
return res.status(200).type('text/html').send(html);
|
499 |
-
}
|
500 |
-
|
501 |
-
|
502 |
-
console.log("--- AI Raw Diff Response ---");
|
503 |
-
console.log(completeResponse);
|
504 |
-
console.log("--------------------------");
|
505 |
-
|
506 |
-
|
507 |
-
// Apply the diffs
|
508 |
-
console.log("[Diff Apply] Attempting to apply diffs...");
|
509 |
-
const modifiedHtml = applyDiffs(html, completeResponse);
|
510 |
-
console.log("[Diff Apply] Diffs applied successfully.");
|
511 |
-
res.status(200).type('text/html').send(modifiedHtml); // Send the fully modified HTML
|
512 |
-
|
513 |
-
} else {
|
514 |
-
// **Stream response directly (Initial Request)**
|
515 |
-
console.log("[AI Request] Starting direct stream for initial request.");
|
516 |
-
res.setHeader("Content-Type", "text/html"); // Send as HTML
|
517 |
-
res.setHeader("Cache-Control", "no-cache");
|
518 |
-
res.setHeader("Connection", "keep-alive");
|
519 |
-
|
520 |
-
for await (const value of chatCompletion) {
|
521 |
-
const chunk = value.choices[0]?.delta?.content;
|
522 |
-
if (chunk) {
|
523 |
-
res.write(chunk);
|
524 |
-
completeResponse += chunk; // Still useful for checking completion
|
525 |
-
}
|
526 |
}
|
|
|
527 |
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
console.log("[AI Request] Stream finished successfully.");
|
534 |
-
}
|
535 |
|
536 |
-
|
537 |
-
}
|
538 |
|
539 |
} catch (error) {
|
540 |
-
console.error("Error during AI interaction or diff application
|
541 |
-
// If we haven't sent
|
542 |
if (!res.headersSent) {
|
543 |
// Check if it's an AbortError which might happen if the client disconnects
|
544 |
if (error.name === 'AbortError') {
|
@@ -549,14 +513,14 @@ ONLY output the changes in this format. Do NOT output the full HTML file again.`
|
|
549 |
res.status(500).send({
|
550 |
ok: false,
|
551 |
// Provide a more user-friendly message, but keep details for logs
|
|
|
552 |
message: `Error processing AI request: ${error.message}. You might need to start a new conversation by refreshing the page.`,
|
553 |
});
|
554 |
-
} else if (!
|
555 |
// If streaming failed mid-stream and stream hasn't been ended yet
|
556 |
-
console.error("Error occurred mid-stream.");
|
557 |
res.end(); // End the stream abruptly if error occurs during streaming
|
558 |
}
|
559 |
-
// If diff application failed, error was already sent by applyDiffs throwing.
|
560 |
// If streaming failed *after* res.end() was called (unlikely but possible), do nothing more.
|
561 |
}
|
562 |
});
|
|
|
467 |
let completeResponse = "";
|
468 |
|
469 |
try {
|
470 |
+
// Set response type header *before* starting the stream
|
471 |
+
res.setHeader("Content-Type", "text/plain; charset=utf-8"); // Stream raw text
|
472 |
+
res.setHeader("Cache-Control", "no-cache");
|
473 |
+
res.setHeader("Connection", "keep-alive");
|
474 |
+
res.setHeader("X-Response-Type", isFollowUp ? "diff" : "full"); // Signal type to client
|
475 |
+
console.log(`[AI Request] Set X-Response-Type: ${isFollowUp ? 'diff' : 'full'}`);
|
476 |
+
|
477 |
const chatCompletion = client.chatCompletionStream({
|
478 |
model: MODEL_ID,
|
479 |
provider: "fireworks-ai", // Ensure provider is correct if needed
|
|
|
482 |
// temperature: 0.7, // Adjust temperature if needed
|
483 |
});
|
484 |
|
485 |
+
// --- Unified Streaming Logic ---
|
486 |
+
console.log("[AI Request] Starting stream to client...");
|
487 |
+
for await (const value of chatCompletion) {
|
488 |
+
const chunk = value.choices[0]?.delta?.content;
|
489 |
+
if (chunk) {
|
490 |
+
res.write(chunk); // Stream raw AI response chunk
|
491 |
+
completeResponse += chunk; // Accumulate for logging completion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
492 |
}
|
493 |
+
}
|
494 |
|
495 |
+
console.log("[AI Request] Stream finished.");
|
496 |
+
// Log the complete raw response for debugging if needed
|
497 |
+
// console.log("--- AI Raw Full Response ---");
|
498 |
+
// console.log(completeResponse);
|
499 |
+
// console.log("--------------------------");
|
|
|
|
|
500 |
|
501 |
+
res.end(); // End the stream
|
|
|
502 |
|
503 |
} catch (error) {
|
504 |
+
console.error("Error during AI interaction:", error); // Removed "or diff application"
|
505 |
+
// If we haven't sent headers/started streaming yet
|
506 |
if (!res.headersSent) {
|
507 |
// Check if it's an AbortError which might happen if the client disconnects
|
508 |
if (error.name === 'AbortError') {
|
|
|
513 |
res.status(500).send({
|
514 |
ok: false,
|
515 |
// Provide a more user-friendly message, but keep details for logs
|
516 |
+
// Provide a more user-friendly message, but keep details for logs
|
517 |
message: `Error processing AI request: ${error.message}. You might need to start a new conversation by refreshing the page.`,
|
518 |
});
|
519 |
+
} else if (!res.writableEnded) {
|
520 |
// If streaming failed mid-stream and stream hasn't been ended yet
|
521 |
+
console.error("Error occurred mid-stream. Ending response.");
|
522 |
res.end(); // End the stream abruptly if error occurs during streaming
|
523 |
}
|
|
|
524 |
// If streaming failed *after* res.end() was called (unlikely but possible), do nothing more.
|
525 |
}
|
526 |
});
|