everydaycats commited on
Commit
e545be1
·
verified ·
1 Parent(s): a216373

Update app.js

Browse files
Files changed (1) hide show
  1. app.js +26 -75
app.js CHANGED
@@ -4,94 +4,58 @@ import { WebSocketServer, WebSocket } from 'ws';
4
  import cors from 'cors';
5
  import { createClient } from '@supabase/supabase-js';
6
 
7
- // --- CONFIG ---
8
  const PORT = 7860;
9
  const SUPABASE_URL = process.env.SUPABASE_URL;
10
  const SUPABASE_KEY = process.env.SUPABASE_SERVICE_KEY;
11
- const CORE_URL = process.env.CORE_URL; // e.g. https://my-core-server.hf.space
12
 
13
- if (!SUPABASE_URL) { console.error("❌ Missing Config"); process.exit(1); }
14
 
15
- // --- STATE ---
16
  const app = express();
17
  const server = createServer(app);
18
  const wss = new WebSocketServer({ noServer: true });
19
  const supabase = createClient(SUPABASE_URL, SUPABASE_KEY);
20
 
21
- // Active Connections: Map<UserId, Set<WebSocket>>
22
- const clients = new Map();
23
 
24
  app.use(cors());
25
- app.use(express.json());
26
 
27
- // --- HTTP ENDPOINTS (Webhooks/Uploads) ---
28
 
29
- app.get('/', (req, res) => res.send('Front Gateway Active'));
30
-
31
- // Internal Endpoint for Core to push notifications to desktop
32
  app.post('/internal/notify', (req, res) => {
33
- const { user_id, type, message, payload } = req.body;
34
-
35
  if (clients.has(user_id)) {
36
- const userSockets = clients.get(user_id);
37
- let count = 0;
38
- userSockets.forEach(ws => {
39
- if (ws.readyState === WebSocket.OPEN) {
40
- ws.send(JSON.stringify({ type, message, payload }));
41
- count++;
42
- }
43
  });
44
- return res.json({ success: true, delivered_to: count });
45
  }
46
-
47
- res.json({ success: false, reason: "User offline" });
48
- });
49
-
50
- // Endpoint for File Uploads (Base64 is easier for single script than Multer)
51
- app.post('/upload', async (req, res) => {
52
- // In a real app, handle streams. Here we assume small/medium files.
53
- // Client sends this to avoid clogging WS.
54
- res.json({ status: "ok", note: "File received (Placeholder logic)" });
55
  });
56
 
57
- // --- WEBSOCKET AUTH & UPGRADE ---
58
-
59
  server.on('upgrade', async (request, socket, head) => {
60
  const url = new URL(request.url, `http://${request.headers.host}`);
61
  const token = url.searchParams.get('token');
62
 
63
- if (!token) {
64
- socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
65
- socket.destroy();
66
- return;
67
- }
68
 
69
- // Validate with Supabase
70
  const { data: { user }, error } = await supabase.auth.getUser(token);
71
-
72
- if (error || !user) {
73
- console.log("❌ WS Auth Failed");
74
- socket.write('HTTP/1.1 403 Forbidden\r\n\r\n');
75
- socket.destroy();
76
- return;
77
- }
78
 
79
  wss.handleUpgrade(request, socket, head, (ws) => {
80
  wss.emit('connection', ws, request, user);
81
  });
82
  });
83
 
84
- // --- WEBSOCKET LOGIC ---
85
-
86
  wss.on('connection', (ws, req, user) => {
87
  const userId = user.id;
88
- console.log(`🔌 Connected: ${userId}`);
89
-
90
- // Register
91
  if (!clients.has(userId)) clients.set(userId, new Set());
92
  clients.get(userId).add(ws);
93
 
94
- // Heartbeat (Keep-Alive for HF Spaces)
95
  ws.isAlive = true;
96
  ws.on('pong', () => { ws.isAlive = true; });
97
 
@@ -99,15 +63,9 @@ wss.on('connection', (ws, req, user) => {
99
  try {
100
  const data = JSON.parse(message.toString());
101
 
102
- // 1. ROUTING: PROMPT -> CORE
103
  if (data.type === 'prompt') {
104
  ws.send(JSON.stringify({ type: 'status', status: 'thinking' }));
105
 
106
- if (!CORE_URL) {
107
- ws.send(JSON.stringify({ type: 'error', message: "Core Server Config Missing" }));
108
- return;
109
- }
110
-
111
  // Call Core
112
  const response = await fetch(`${CORE_URL}/process`, {
113
  method: 'POST',
@@ -116,37 +74,34 @@ wss.on('connection', (ws, req, user) => {
116
  userId: userId,
117
  projectId: data.projectId,
118
  prompt: data.content,
119
- context: data.context
 
120
  })
121
  });
122
 
123
  const result = await response.json();
124
 
125
- // Send Result to Client
126
  ws.send(JSON.stringify({
127
  type: 'response',
128
  text: result.text,
129
- should_reload: result.should_reload
 
130
  }));
131
  }
132
-
133
  } catch (e) {
134
- console.error("WS Message Error", e);
135
- ws.send(JSON.stringify({ type: 'error', message: "Server Error" }));
136
  }
137
  });
138
 
139
  ws.on('close', () => {
140
- if (clients.has(userId)) {
141
- clients.get(userId).delete(ws);
142
- if (clients.get(userId).size === 0) clients.delete(userId);
143
- }
144
- console.log(`❌ Disconnected: ${userId}`);
145
  });
146
  });
147
 
148
- // Heartbeat Interval (30s)
149
- const interval = setInterval(() => {
150
  wss.clients.forEach((ws) => {
151
  if (ws.isAlive === false) return ws.terminate();
152
  ws.isAlive = false;
@@ -154,8 +109,4 @@ const interval = setInterval(() => {
154
  });
155
  }, 30000);
156
 
157
- wss.on('close', () => clearInterval(interval));
158
-
159
- server.listen(PORT, () => {
160
- console.log(`🚀 Front Gateway running on port ${PORT}`);
161
- });
 
4
  import cors from 'cors';
5
  import { createClient } from '@supabase/supabase-js';
6
 
 
7
  const PORT = 7860;
8
  const SUPABASE_URL = process.env.SUPABASE_URL;
9
  const SUPABASE_KEY = process.env.SUPABASE_SERVICE_KEY;
10
+ const CORE_URL = process.env.CORE_URL;
11
 
12
+ if (!SUPABASE_URL) { console.error("❌ Config Missing"); process.exit(1); }
13
 
 
14
  const app = express();
15
  const server = createServer(app);
16
  const wss = new WebSocketServer({ noServer: true });
17
  const supabase = createClient(SUPABASE_URL, SUPABASE_KEY);
18
 
19
+ const clients = new Map(); // UserId -> Set<WebSocket>
 
20
 
21
  app.use(cors());
22
+ app.use(express.json({ limit: '50mb' }));
23
 
24
+ app.get('/', (req, res) => res.send('Gateway Active'));
25
 
26
+ // Internal Notification Webhook
 
 
27
  app.post('/internal/notify', (req, res) => {
28
+ const { user_id, type, message } = req.body;
 
29
  if (clients.has(user_id)) {
30
+ clients.get(user_id).forEach(ws => {
31
+ if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type, message }));
 
 
 
 
 
32
  });
33
+ return res.json({ success: true });
34
  }
35
+ res.json({ success: false });
 
 
 
 
 
 
 
 
36
  });
37
 
38
+ // WS Upgrade
 
39
  server.on('upgrade', async (request, socket, head) => {
40
  const url = new URL(request.url, `http://${request.headers.host}`);
41
  const token = url.searchParams.get('token');
42
 
43
+ if (!token) { socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n'); socket.destroy(); return; }
 
 
 
 
44
 
 
45
  const { data: { user }, error } = await supabase.auth.getUser(token);
46
+ if (error || !user) { socket.write('HTTP/1.1 403 Forbidden\r\n\r\n'); socket.destroy(); return; }
 
 
 
 
 
 
47
 
48
  wss.handleUpgrade(request, socket, head, (ws) => {
49
  wss.emit('connection', ws, request, user);
50
  });
51
  });
52
 
53
+ // WS Logic
 
54
  wss.on('connection', (ws, req, user) => {
55
  const userId = user.id;
 
 
 
56
  if (!clients.has(userId)) clients.set(userId, new Set());
57
  clients.get(userId).add(ws);
58
 
 
59
  ws.isAlive = true;
60
  ws.on('pong', () => { ws.isAlive = true; });
61
 
 
63
  try {
64
  const data = JSON.parse(message.toString());
65
 
 
66
  if (data.type === 'prompt') {
67
  ws.send(JSON.stringify({ type: 'status', status: 'thinking' }));
68
 
 
 
 
 
 
69
  // Call Core
70
  const response = await fetch(`${CORE_URL}/process`, {
71
  method: 'POST',
 
74
  userId: userId,
75
  projectId: data.projectId,
76
  prompt: data.content,
77
+ context: data.context,
78
+ history: data.history
79
  })
80
  });
81
 
82
  const result = await response.json();
83
 
84
+ // Send to Client
85
  ws.send(JSON.stringify({
86
  type: 'response',
87
  text: result.text,
88
+ should_reload: result.should_reload, // .NET app listens for this to refresh UI
89
+ usage: result.usage
90
  }));
91
  }
 
92
  } catch (e) {
93
+ console.error("WS Error", e);
94
+ ws.send(JSON.stringify({ type: 'error', message: "Processing Error" }));
95
  }
96
  });
97
 
98
  ws.on('close', () => {
99
+ if (clients.has(userId)) clients.get(userId).delete(ws);
 
 
 
 
100
  });
101
  });
102
 
103
+ // Keep Alive
104
+ setInterval(() => {
105
  wss.clients.forEach((ws) => {
106
  if (ws.isAlive === false) return ws.terminate();
107
  ws.isAlive = false;
 
109
  });
110
  }, 30000);
111
 
112
+ server.listen(PORT, () => console.log(`🚀 Gateway on ${PORT}`));