everydaytok commited on
Commit
daa0c79
·
verified ·
1 Parent(s): b9c9353

Delete app2.js

Browse files
Files changed (1) hide show
  1. app2.js +0 -417
app2.js DELETED
@@ -1,417 +0,0 @@
1
- import express from 'express';
2
- import bodyParser from 'body-parser';
3
- import cors from 'cors';
4
- import { StateManager } from './stateManager.js';
5
- import { AIEngine } from './aiEngine.js';
6
- import fs from 'fs';
7
- import admin from 'firebase-admin';
8
-
9
- // --- FIREBASE SETUP ---
10
- // Using environment variable injection as requested
11
- let db = null;
12
- try {
13
- if (process.env.FIREBASE_SERVICE_ACCOUNT_JSON && process.env.FIREBASE_SERVICE_ACCOUNT_JSON !== "") {
14
- const serviceAccount = JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT_JSON);
15
- admin.initializeApp({
16
- credential: admin.credential.cert(serviceAccount),
17
- // Make sure to replace this URL or add it to env variables as well
18
- databaseURL: "https://shago-web-default-rtdb.firebaseio.com"
19
- });
20
- db = admin.database();
21
- console.log("🔥 Firebase Connected");
22
- } else {
23
- console.warn("⚠️ No FIREBASE_SERVICE_ACCOUNT_JSON found. Running in Memory-Only mode.");
24
- }
25
- } catch (e) {
26
- console.error("Firebase Init Error:", e);
27
- }
28
-
29
- const app = express();
30
- const PORT = process.env.PORT || 7860;
31
-
32
- // Load Prompts for Server-Side Logic Checks
33
- const sysPrompts = JSON.parse(fs.readFileSync('./prompts.json', 'utf8'));
34
-
35
- app.use(cors());
36
- app.use(bodyParser.json({ limit: '50mb' }));
37
-
38
- // --- HELPERS ---
39
- const validateRequest = (req, res, next) => {
40
- if (req.path.includes('/onboarding')) return next();
41
-
42
- const { userId, projectId } = req.body;
43
- if (!userId || !projectId) return res.status(400).json({ error: "Missing ID" });
44
- next();
45
- };
46
-
47
- function extractWorkerPrompt(text) {
48
- const match = text.match(/WORKER_PROMPT:\s*(.*)/s);
49
- return match ? match[1].trim() : null;
50
- }
51
-
52
- function formatContext({ hierarchyContext, scriptContext, logContext }) {
53
- let out = "";
54
- if (scriptContext) out += `\n[TARGET SCRIPT]: ${scriptContext.targetName}\n[SOURCE PREVIEW]: ${scriptContext.scriptSource?.substring(0, 1000)}...`;
55
- if (logContext) out += `\n[LAST LOGS]: ${logContext.logs}`;
56
- return out;
57
- }
58
-
59
- function extractPMQuestion(text) {
60
- const match = text.match(/\[ASK_PM:\s*(.*?)\]/s);
61
- return match ? match[1].trim() : null;
62
- }
63
-
64
- function extractImagePrompt(text) {
65
- const match = text.match(/\[GENERATE_IMAGE:\s*(.*?)\]/s);
66
- return match ? match[1].trim() : null;
67
- }
68
-
69
- // --- ONBOARDING ENDPOINTS ---
70
- /**
71
- * 1. ANALYZE
72
- */
73
- app.post('/onboarding/analyze', validateRequest, async (req, res) => {
74
- const { description } = req.body;
75
- if (!description) return res.status(400).json({ error: "Description required" });
76
-
77
- try {
78
- console.log(`[Onboarding] Analyzing idea...`);
79
- const result = await AIEngine.generateEntryQuestions(description);
80
-
81
- if (result.status === "REJECTED") {
82
- return res.json({
83
- rejected: true,
84
- reason: result.reason || "Idea violates TOS or guidelines."
85
- });
86
- }
87
- res.json({ questions: result.questions });
88
- } catch (err) {
89
- console.error(err);
90
- res.status(500).json({ error: "Analysis failed" });
91
- }
92
- });
93
-
94
- /**
95
- * 2. CREATE
96
- */
97
- app.post('/onboarding/create', validateRequest, async (req, res) => {
98
- const { userId, description, answers } = req.body;
99
- const projectId = "proj_" + Date.now();
100
-
101
- try {
102
- console.log(`[Onboarding] Grading Project ${projectId}...`);
103
-
104
- // STEP 1: GRADE
105
- const grading = await AIEngine.gradeProject(description, answers);
106
-
107
- // STEP 2: CHECK FAIL CONDITIONS (Relaxed)
108
- // Only fail if Feasibility is extremely low (< 30) or Rating is F
109
- const isFailure = grading.feasibility < 30 || grading.rating === 'F';
110
-
111
- let thumbnailBase64 = null;
112
-
113
- if (isFailure) {
114
- console.log(`[Onboarding] ❌ Project Failed Grading (${grading.rating}). Skipping Image.`);
115
- } else {
116
- console.log(`[Onboarding] ✅ Passed. Generating Thumbnail...`);
117
-
118
- // --- CRITICAL FIX HERE ---
119
- // We MUST send the description so the AI knows what to draw.
120
- const imagePrompt = `Game Title: ${grading.title}. Core Concept: ${description}`;
121
- thumbnailBase64 = await AIEngine.generateImage(imagePrompt);
122
- }
123
-
124
- const projectData = {
125
- id: projectId,
126
- userId,
127
- title: grading.title || "Untitled Project",
128
- description,
129
- answers,
130
- stats: grading,
131
- thumbnail: thumbnailBase64, // ? `data:image/png;base64,${thumbnailBase64}` : null,
132
- createdAt: Date.now(),
133
- status: isFailure ? "rejected" : "initialized"
134
- };
135
-
136
- if (db) await db.ref(`projects/${projectId}`).set(projectData);
137
-
138
- if (!isFailure) {
139
- await StateManager.updateProject(projectId, {
140
- ...projectData,
141
- workerHistory: [],
142
- pmHistory: [],
143
- failureCount: 0
144
- });
145
- }
146
-
147
- res.json({
148
- success: !isFailure,
149
- projectId,
150
- stats: grading,
151
- title: projectData.title,
152
- thumbnail: projectData.thumbnail
153
- });
154
-
155
- } catch (err) {
156
- console.error("Create Error:", err);
157
- res.status(500).json({ error: "Creation failed" });
158
- }
159
- });
160
-
161
-
162
- // --- CORE WORKFLOW ENDPOINTS ---
163
-
164
- /**
165
- * 3. INITIALIZE WORKSPACE (PM Generates GDD -> First Task)
166
- */
167
- app.post('/new/project', validateRequest, async (req, res) => {
168
- const { userId, projectId, description } = req.body;
169
-
170
- try {
171
- const pmHistory = [];
172
- const gddPrompt = `Create a comprehensive GDD for: ${description}`;
173
- const gddResponse = await AIEngine.callPM(pmHistory, gddPrompt);
174
-
175
- pmHistory.push({ role: 'user', parts: [{ text: gddPrompt }] });
176
- pmHistory.push({ role: 'model', parts: [{ text: gddResponse }] });
177
-
178
- const taskPrompt = "Based on the GDD, generate the first technical milestone.\nOutput format:\nTASK_NAME: <Name>\nWORKER_PROMPT: <Specific, isolated instructions for the worker>";
179
- const taskResponse = await AIEngine.callPM(pmHistory, taskPrompt);
180
-
181
- pmHistory.push({ role: 'user', parts: [{ text: taskPrompt }] });
182
- pmHistory.push({ role: 'model', parts: [{ text: taskResponse }] });
183
-
184
- const initialWorkerInstruction = extractWorkerPrompt(taskResponse) || `Initialize structure for: ${description}`;
185
-
186
- const workerHistory = [];
187
- const initialWorkerPrompt = `CONTEXT: New Project. \nINSTRUCTION: ${initialWorkerInstruction}`;
188
- const workerResponse = await AIEngine.callWorker(workerHistory, initialWorkerPrompt, []);
189
-
190
- workerHistory.push({ role: 'user', parts: [{ text: initialWorkerPrompt }] });
191
- workerHistory.push({ role: 'model', parts: [{ text: workerResponse }] });
192
-
193
- // Update State
194
- await StateManager.updateProject(projectId, {
195
- userId,
196
- pmHistory,
197
- workerHistory,
198
- gdd: gddResponse,
199
- failureCount: 0
200
- });
201
-
202
- // Queue Actions
203
- await processAndQueueResponse(projectId, workerResponse);
204
-
205
- res.json({ success: true, message: "Workspace Initialized", gddPreview: gddResponse.substring(0, 200) });
206
-
207
- } catch (err) {
208
- console.error("Init Error:", err);
209
- res.status(500).json({ error: "Initialization Failed" });
210
- }
211
- });
212
-
213
- /**
214
- * 4. FEEDBACK LOOP (The "Brain")
215
- */
216
- app.post('/project/feedback', async (req, res) => {
217
- const { projectId, prompt, hierarchyContext, scriptContext, logContext, taskComplete, images } = req.body;
218
-
219
- const project = await StateManager.getProject(projectId);
220
- if (!project) return res.status(404).json({ error: "Project not found." });
221
-
222
- // A. TASK COMPLETE -> SCOPE SWITCH
223
- if (taskComplete) {
224
- console.log(`[${projectId}] ✅ TASK COMPLETE.`);
225
-
226
- const summary = `Worker completed the previous task. Logs: ${logContext?.logs || "Clean"}. \nGenerate the NEXT task using 'WORKER_PROMPT:' format.`;
227
- const pmResponse = await AIEngine.callPM(project.pmHistory, summary);
228
-
229
- project.pmHistory.push({ role: 'user', parts: [{ text: summary }] });
230
- project.pmHistory.push({ role: 'model', parts: [{ text: pmResponse }] });
231
-
232
- const nextInstruction = extractWorkerPrompt(pmResponse);
233
- if (!nextInstruction) {
234
- await StateManager.updateProject(projectId, { pmHistory: project.pmHistory, status: "IDLE" });
235
- return res.json({ success: true, message: "No further tasks. Project Idle." });
236
- }
237
-
238
- console.log(`[${projectId}] 🧹 Nuking Worker for next task.`);
239
- const newWorkerHistory = [];
240
- const newPrompt = `New Objective: ${nextInstruction}`;
241
- const workerResponse = await AIEngine.callWorker(newWorkerHistory, newPrompt, []);
242
-
243
- newWorkerHistory.push({ role: 'user', parts: [{ text: newPrompt }] });
244
- newWorkerHistory.push({ role: 'model', parts: [{ text: workerResponse }] });
245
-
246
- await StateManager.updateProject(projectId, {
247
- pmHistory: project.pmHistory,
248
- workerHistory: newWorkerHistory,
249
- failureCount: 0
250
- });
251
-
252
- StateManager.queueCommand(projectId, { type: "EXECUTE", payload: "warn('Starting Next Task...')" });
253
- await processAndQueueResponse(projectId, workerResponse);
254
-
255
- return res.json({ success: true, message: "Next Task Assigned" });
256
- }
257
-
258
- // B. ERROR ESCALATION
259
- let isFailure = false;
260
- if (logContext?.logs) {
261
- const errs = ["Error", "Exception", "failed", "Stack Begin", "Infinite yield"];
262
- if (errs.some(k => logContext.logs.includes(k))) {
263
- isFailure = true;
264
- project.failureCount = (project.failureCount || 0) + 1;
265
- }
266
- }
267
-
268
- if (project.failureCount > 3) {
269
- console.log(`[${projectId}] 🚨 Escalating to PM...`);
270
- const pmPrompt = sysPrompts.pm_guidance_prompt.replace('{{LOGS}}', logContext?.logs);
271
- const pmVerdict = await AIEngine.callPM(project.pmHistory, pmPrompt);
272
-
273
- if (pmVerdict.includes("[TERMINATE]")) {
274
- const fixInstruction = pmVerdict.replace("[TERMINATE]", "").trim();
275
- const resetHistory = [];
276
- const resetPrompt = `[SYSTEM]: Previous worker terminated. \nNew Objective: ${fixInstruction}`;
277
- const workerResp = await AIEngine.callWorker(resetHistory, resetPrompt, []);
278
-
279
- resetHistory.push({ role: 'user', parts: [{ text: resetPrompt }] });
280
- resetHistory.push({ role: 'model', parts: [{ text: workerResp }] });
281
-
282
- await StateManager.updateProject(projectId, { workerHistory: resetHistory, failureCount: 0 });
283
- StateManager.queueCommand(projectId, { type: "EXECUTE", payload: "print('SYSTEM: Worker Reset')" });
284
- await processAndQueueResponse(projectId, workerResp);
285
-
286
- return res.json({ success: true, message: "Worker Terminated." });
287
- } else {
288
- const injection = `[PM GUIDANCE]: ${pmVerdict} \n\nApply this fix now.`;
289
- const workerResp = await AIEngine.callWorker(project.workerHistory, injection, []);
290
-
291
- project.workerHistory.push({ role: 'user', parts: [{ text: injection }] });
292
- project.workerHistory.push({ role: 'model', parts: [{ text: workerResp }] });
293
-
294
- await StateManager.updateProject(projectId, { workerHistory: project.workerHistory, failureCount: 1 });
295
- await processAndQueueResponse(projectId, workerResp);
296
-
297
- return res.json({ success: true, message: "PM Guidance Applied." });
298
- }
299
- }
300
-
301
- // C. STANDARD LOOP + CONSULTATION
302
- try {
303
- const fullInput = `USER: ${prompt || "Automatic Feedback"}` + formatContext({ hierarchyContext, scriptContext, logContext });
304
-
305
- let response = await AIEngine.callWorker(project.workerHistory, fullInput, images || []);
306
-
307
- // CHECK: Consultant Question
308
- const pmQuestion = extractPMQuestion(response);
309
- if (pmQuestion) {
310
- console.log(`[${projectId}] 🙋 Worker asking PM: "${pmQuestion}"`);
311
-
312
- const pmConsultPrompt = `[WORKER CONSULTATION]: The Worker asks: "${pmQuestion}"\nProvide a technical answer to unblock them.`;
313
- const pmAnswer = await AIEngine.callPM(project.pmHistory, pmConsultPrompt);
314
-
315
- // Update PM Context
316
- project.pmHistory.push({ role: 'user', parts: [{ text: pmConsultPrompt }] });
317
- project.pmHistory.push({ role: 'model', parts: [{ text: pmAnswer }] });
318
-
319
- // Feed Answer Back
320
- const injectionMsg = `[PM RESPONSE]: ${pmAnswer}`;
321
- project.workerHistory.push({ role: 'user', parts: [{ text: fullInput }] });
322
- project.workerHistory.push({ role: 'model', parts: [{ text: response }] });
323
-
324
- // Resume Worker
325
- response = await AIEngine.callWorker(project.workerHistory, injectionMsg, []);
326
- project.workerHistory.push({ role: 'user', parts: [{ text: injectionMsg }] });
327
- project.workerHistory.push({ role: 'model', parts: [{ text: response }] });
328
- } else {
329
- project.workerHistory.push({ role: 'user', parts: [{ text: fullInput }] });
330
- project.workerHistory.push({ role: 'model', parts: [{ text: response }] });
331
- }
332
-
333
- await StateManager.updateProject(projectId, {
334
- workerHistory: project.workerHistory,
335
- pmHistory: project.pmHistory,
336
- failureCount: project.failureCount
337
- });
338
-
339
- await processAndQueueResponse(projectId, response);
340
- res.json({ success: true });
341
-
342
- } catch (err) {
343
- console.error("AI Error:", err);
344
- res.status(500).json({ error: "AI Failed" });
345
- }
346
- });
347
-
348
- /**
349
- * 5. PING (Plugin Polling)
350
- */
351
- app.post('/project/ping', async (req, res) => {
352
- const { projectId } = req.body;
353
- const command = await StateManager.popCommand(projectId);
354
-
355
- if (command) {
356
- if (command.payload === "CLEAR_CONSOLE") {
357
- res.json({ action: "CLEAR_LOGS" });
358
- } else {
359
- res.json({
360
- action: command.type,
361
- target: command.payload,
362
- code: command.type === 'EXECUTE' ? command.payload : null
363
- });
364
- }
365
- } else {
366
- res.json({ action: "IDLE" });
367
- }
368
- });
369
-
370
- /**
371
- * 6. MANUAL OVERRIDE
372
- */
373
- app.post('/human/override', validateRequest, async (req, res) => {
374
- const { projectId, instruction, pruneHistory } = req.body;
375
- const project = await StateManager.getProject(projectId);
376
-
377
- const overrideMsg = `[SYSTEM OVERRIDE]: ${instruction}`;
378
-
379
- if (pruneHistory && project.workerHistory.length >= 2) {
380
- project.workerHistory.pop();
381
- project.workerHistory.pop();
382
- }
383
-
384
- const response = await AIEngine.callWorker(project.workerHistory, overrideMsg, []);
385
- project.workerHistory.push({ role: 'user', parts: [{ text: overrideMsg }] });
386
- project.workerHistory.push({ role: 'model', parts: [{ text: response }] });
387
-
388
- await StateManager.updateProject(projectId, { workerHistory: project.workerHistory });
389
- await processAndQueueResponse(projectId, response);
390
- res.json({ success: true });
391
- });
392
-
393
-
394
- // --- RESPONSE PROCESSOR ---
395
- async function processAndQueueResponse(projectId, rawResponse) {
396
- // 1. Intercept Image Requests
397
- const imgPrompt = extractImagePrompt(rawResponse);
398
- if (imgPrompt) {
399
- console.log(`[${projectId}] 🎨 Generating Asset: ${imgPrompt}`);
400
- const base64Image = await AIEngine.generateImage(imgPrompt);
401
-
402
- if (base64Image) {
403
- // Queue asset creation for Plugin
404
- await StateManager.queueCommand(projectId, {
405
- type: "CREATE_ASSET",
406
- payload: base64Image
407
- });
408
- }
409
- }
410
-
411
- // 2. Queue the Raw Response (StateManager parses code)
412
- await StateManager.queueCommand(projectId, rawResponse);
413
- }
414
-
415
- app.listen(PORT, () => {
416
- console.log(`AI Backend Running on ${PORT}`);
417
- });