Skip to content

Commit 18455d5

Browse files
committed
feat: implement collaborative workspace socket server with Yjs, AI assistance, and real-time canvas support
1 parent a9079cc commit 18455d5

1 file changed

Lines changed: 58 additions & 6 deletions

File tree

server/sockets/collaborativeWorkspace.js

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -416,8 +416,10 @@ async function handleForgeAIMessage(roomId, io, text) {
416416

417417
try {
418418
const geminiApiKey = process.env.GEMINI_API_KEY;
419-
if (!geminiApiKey) {
420-
throw new Error("Gemini API key is not configured on the server.");
419+
const groqApiKey = process.env.GROQ_API_KEY;
420+
421+
if (!geminiApiKey && !groqApiKey) {
422+
throw new Error("No Gemini or Groq API key configured on the server.");
421423
}
422424

423425
const currentCode = workspace.yDoc ? workspace.yDoc.getText('monaco').toString() : '';
@@ -440,10 +442,60 @@ Schema:
440442
}
441443
`;
442444

443-
const genAI = new GoogleGenerativeAI(geminiApiKey);
444-
const model = genAI.getGenerativeModel({ model: 'gemini-2.5-flash' });
445-
const result = await model.generateContent(systemPrompt);
446-
const responseText = result.response.text();
445+
let responseText = '';
446+
let success = false;
447+
let lastError = null;
448+
449+
// 1. Try Gemini first
450+
if (geminiApiKey) {
451+
try {
452+
console.log(`[ForgeAI] Attempting Gemini query...`);
453+
const genAI = new GoogleGenerativeAI(geminiApiKey);
454+
const model = genAI.getGenerativeModel({ model: 'gemini-2.5-flash' });
455+
const result = await model.generateContent(systemPrompt);
456+
responseText = result.response.text();
457+
success = true;
458+
} catch (geminiError) {
459+
console.warn(`[ForgeAI] Gemini failed. Trying Groq fallback...`, geminiError);
460+
lastError = geminiError;
461+
}
462+
}
463+
464+
// 2. Try Groq fallback
465+
if (!success && groqApiKey) {
466+
try {
467+
console.log(`[ForgeAI] Attempting Groq fallback...`);
468+
const response = await fetch('https://api.groq.com/openai/v1/chat/completions', {
469+
method: 'POST',
470+
headers: {
471+
'Authorization': `Bearer ${groqApiKey}`,
472+
'Content-Type': 'application/json'
473+
},
474+
body: JSON.stringify({
475+
model: 'llama-3.3-70b-versatile',
476+
messages: [{ role: 'user', content: systemPrompt }],
477+
temperature: 0.15,
478+
response_format: { type: "json_object" }
479+
})
480+
});
481+
482+
if (!response.ok) {
483+
const errText = await response.text();
484+
throw new Error(`Groq API returned status ${response.status}: ${errText}`);
485+
}
486+
487+
const json = await response.json();
488+
responseText = json.choices?.[0]?.message?.content || '';
489+
success = true;
490+
} catch (groqError) {
491+
console.error(`[ForgeAI] Groq fallback failed:`, groqError);
492+
lastError = groqError;
493+
}
494+
}
495+
496+
if (!success) {
497+
throw new Error(lastError?.message || 'No Gemini or Groq API Keys configured for ForgeAI.');
498+
}
447499

448500
// Parse response
449501
let parsed;

0 commit comments

Comments
 (0)