Pepguy commited on
Commit
427de73
·
verified ·
1 Parent(s): ef9a0f0

Update app.js

Browse files
Files changed (1) hide show
  1. app.js +13 -24
app.js CHANGED
@@ -1,4 +1,4 @@
1
- // server.js - ALIGNED WITH PLUGIN
2
  // Run: GEMINI_API_KEY=your_key node server.js
3
 
4
  import express from "express";
@@ -25,7 +25,6 @@ const simpleId = (prefix = "") => prefix + Math.random().toString(36).slice(2, 9
25
  /**
26
  * STRICT VOCABULARY
27
  * Only actions that exist in the Plugin's ACTION_HANDLERS are allowed here.
28
- * Removed: create_union, create_rig, apply_animation, unweld, apply_texture
29
  */
30
  const VALID_ACTIONS = [
31
  "create_part",
@@ -40,7 +39,7 @@ const VALID_ACTIONS = [
40
  "set_parent",
41
  "delete",
42
  "weld",
43
- "list_workspace", // Plugin calls this workspaceSnapshot
44
  "finish"
45
  ];
46
 
@@ -69,12 +68,12 @@ const ACTION_SYNONYMS = {
69
  "group": "create_model",
70
  "parent": "set_parent",
71
  "set_parent_to": "set_parent",
72
- "join": "weld", -- "Join" usually implies welding in this simple context
73
 
74
  // Unsupported fallbacks (Safety)
75
- "union": "create_model", -- Fallback: Group them instead of Unioning (prevents crash)
76
  "create_union": "create_model",
77
- "create_rig": "create_model" -- Fallback: Just make a model container
78
  };
79
 
80
  function validateAndPrepareTasks(arr) {
@@ -100,8 +99,6 @@ function validateAndPrepareTasks(arr) {
100
  }
101
 
102
  if (!canonicalAction) {
103
- // If AI hallucinates an action, we force it to a safe fallback or error
104
- // Instead of crashing, let's log it and skip or error.
105
  throw new Error(`Invalid action '${actionRaw}'. Supported: ${VALID_ACTIONS.join(", ")}`);
106
  }
107
 
@@ -119,7 +116,6 @@ function validateAndPrepareTasks(arr) {
119
  }
120
 
121
  async function generateTasks(project) {
122
- // Summarize project state
123
  const historySample = (project.history || []).slice(-15).map(h => ({
124
  status: h.status,
125
  action: h.originalAction || "unknown",
@@ -128,7 +124,6 @@ async function generateTasks(project) {
128
 
129
  const status = project.status || "unknown";
130
 
131
- // We explicitly tell the AI about the Registry logic in the prompt
132
  const systemPrompt = `
133
  You are a Roblox Studio Assistant. Convert user descriptions into JSON tasks.
134
 
@@ -152,17 +147,18 @@ User Request:
152
  ${JSON.stringify({ description: project.description })}
153
  `;
154
 
 
 
155
  const resp = await ai.models.generateContent({
156
- model: "gemini-2.0-flash", // Updated to latest flash if available, or use 1.5-flash
157
  contents: systemPrompt,
158
- generationConfig: { responseMimeType: "application/json" } // Force JSON mode
159
  });
160
 
161
  const text = resp?.text ? resp.text() : (resp?.response?.text() ?? "");
162
 
163
  let arr;
164
  try {
165
- // Clean markdown code blocks if present
166
  const cleanText = text.replace(/```json/g, "").replace(/```/g, "").trim();
167
  arr = JSON.parse(cleanText);
168
  } catch (err) {
@@ -173,7 +169,7 @@ ${JSON.stringify({ description: project.description })}
173
  return validateAndPrepareTasks(arr);
174
  }
175
 
176
- // --- EXPRESS ROUTES (Same as before, simplified) ---
177
 
178
  app.post("/projects", async (req, res) => {
179
  try {
@@ -189,7 +185,7 @@ app.post("/projects", async (req, res) => {
189
  _refs: {}
190
  };
191
  projects.set(projectId, project);
192
- runProject(project); // Background run
193
  return res.status(202).json({ projectId, status: "accepted" });
194
  } catch (err) {
195
  return res.status(500).json({ error: err.message });
@@ -201,14 +197,12 @@ app.post("/projects/:projectId/prompt", async (req, res) => {
201
  if (!project) return res.status(404).json({ error: "project not found" });
202
 
203
  const prompt = req.body.prompt;
204
- // Append new prompt to description acts as "memory" for this simple prototype
205
  project.description += `\nUser Update: ${prompt}`;
206
 
207
- // Re-run generation logic for the new prompt
208
  try {
209
- const newTasks = await generateTasks({ ...project, description: prompt }); // Only send the *new* prompt as the task trigger
210
  project.tasks.push(...newTasks);
211
- project.commandQueue.push(...newTasks); // Push directly to queue if already running
212
  return res.json({ tasks: newTasks });
213
  } catch(e) {
214
  return res.status(500).json({error: e.message});
@@ -230,10 +224,8 @@ app.post("/projects/:projectId/result", (req, res) => {
230
 
231
  const { commandId, status, message, target_ref } = req.body;
232
 
233
- // Log history
234
  project.history.push({ commandId, status, message, timestamp: Date.now() });
235
 
236
- // Resolve waiting promise (if runProject is waiting)
237
  if (project.pendingResults.has(commandId)) {
238
  project.pendingResults.get(commandId).resolve({ status, message, target_ref });
239
  project.pendingResults.delete(commandId);
@@ -252,9 +244,6 @@ async function runProject(project) {
252
  return;
253
  }
254
  }
255
-
256
- // In this simplified version, we just let the /next endpoint drain the queue.
257
- // We don't strictly "block" here, making it more robust for connection drops.
258
  }
259
 
260
  app.listen(PORT, () => console.log(`BloxBuddy Brain running on ${PORT}`));
 
1
+ // server.js - ALIGNED WITH PLUGIN & FIXED SYNTAX
2
  // Run: GEMINI_API_KEY=your_key node server.js
3
 
4
  import express from "express";
 
25
  /**
26
  * STRICT VOCABULARY
27
  * Only actions that exist in the Plugin's ACTION_HANDLERS are allowed here.
 
28
  */
29
  const VALID_ACTIONS = [
30
  "create_part",
 
39
  "set_parent",
40
  "delete",
41
  "weld",
42
+ "list_workspace",
43
  "finish"
44
  ];
45
 
 
68
  "group": "create_model",
69
  "parent": "set_parent",
70
  "set_parent_to": "set_parent",
71
+ "join": "weld", // Fixed: JS comment syntax
72
 
73
  // Unsupported fallbacks (Safety)
74
+ "union": "create_model", // Fixed: JS comment syntax
75
  "create_union": "create_model",
76
+ "create_rig": "create_model" // Fixed: JS comment syntax
77
  };
78
 
79
  function validateAndPrepareTasks(arr) {
 
99
  }
100
 
101
  if (!canonicalAction) {
 
 
102
  throw new Error(`Invalid action '${actionRaw}'. Supported: ${VALID_ACTIONS.join(", ")}`);
103
  }
104
 
 
116
  }
117
 
118
  async function generateTasks(project) {
 
119
  const historySample = (project.history || []).slice(-15).map(h => ({
120
  status: h.status,
121
  action: h.originalAction || "unknown",
 
124
 
125
  const status = project.status || "unknown";
126
 
 
127
  const systemPrompt = `
128
  You are a Roblox Studio Assistant. Convert user descriptions into JSON tasks.
129
 
 
147
  ${JSON.stringify({ description: project.description })}
148
  `;
149
 
150
+ // Use gemini-1.5-flash or 2.0-flash depending on what you have access to.
151
+ // 1.5-flash is very stable.
152
  const resp = await ai.models.generateContent({
153
+ model: "gemini-1.5-flash",
154
  contents: systemPrompt,
155
+ generationConfig: { responseMimeType: "application/json" }
156
  });
157
 
158
  const text = resp?.text ? resp.text() : (resp?.response?.text() ?? "");
159
 
160
  let arr;
161
  try {
 
162
  const cleanText = text.replace(/```json/g, "").replace(/```/g, "").trim();
163
  arr = JSON.parse(cleanText);
164
  } catch (err) {
 
169
  return validateAndPrepareTasks(arr);
170
  }
171
 
172
+ // --- EXPRESS ROUTES ---
173
 
174
  app.post("/projects", async (req, res) => {
175
  try {
 
185
  _refs: {}
186
  };
187
  projects.set(projectId, project);
188
+ runProject(project);
189
  return res.status(202).json({ projectId, status: "accepted" });
190
  } catch (err) {
191
  return res.status(500).json({ error: err.message });
 
197
  if (!project) return res.status(404).json({ error: "project not found" });
198
 
199
  const prompt = req.body.prompt;
 
200
  project.description += `\nUser Update: ${prompt}`;
201
 
 
202
  try {
203
+ const newTasks = await generateTasks({ ...project, description: prompt });
204
  project.tasks.push(...newTasks);
205
+ project.commandQueue.push(...newTasks);
206
  return res.json({ tasks: newTasks });
207
  } catch(e) {
208
  return res.status(500).json({error: e.message});
 
224
 
225
  const { commandId, status, message, target_ref } = req.body;
226
 
 
227
  project.history.push({ commandId, status, message, timestamp: Date.now() });
228
 
 
229
  if (project.pendingResults.has(commandId)) {
230
  project.pendingResults.get(commandId).resolve({ status, message, target_ref });
231
  project.pendingResults.delete(commandId);
 
244
  return;
245
  }
246
  }
 
 
 
247
  }
248
 
249
  app.listen(PORT, () => console.log(`BloxBuddy Brain running on ${PORT}`));