From 93282de41d78c9c024c9fa395d5088aec91416f4 Mon Sep 17 00:00:00 2001 From: WEVAL Date: Fri, 3 Apr 2026 05:48:03 +0200 Subject: [PATCH] add edge-proxy --- edge-proxy/fly.toml | 15 ++++++++ edge-proxy/package.json | 8 ++++ edge-proxy/railway.json | 5 +++ edge-proxy/server.js | 81 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+) create mode 100644 edge-proxy/fly.toml create mode 100644 edge-proxy/package.json create mode 100644 edge-proxy/railway.json create mode 100644 edge-proxy/server.js diff --git a/edge-proxy/fly.toml b/edge-proxy/fly.toml new file mode 100644 index 000000000..e13daa850 --- /dev/null +++ b/edge-proxy/fly.toml @@ -0,0 +1,15 @@ +app = "weval-edge" +primary_region = "cdg" + +[build] + builder = "heroku/builder:22" + +[http_service] + internal_port = 3000 + force_https = true + auto_stop_machines = "stop" + auto_start_machines = true + min_machines_running = 0 + +[env] + PORT = "3000" diff --git a/edge-proxy/package.json b/edge-proxy/package.json new file mode 100644 index 000000000..02e43309e --- /dev/null +++ b/edge-proxy/package.json @@ -0,0 +1,8 @@ +{ + "name": "weval-edge-proxy", + "version": "1.0.0", + "description": "WEVAL Sovereign AI Edge Proxy", + "main": "server.js", + "scripts": { "start": "node server.js" }, + "engines": { "node": ">=18" } +} diff --git a/edge-proxy/railway.json b/edge-proxy/railway.json new file mode 100644 index 000000000..64a16c4d6 --- /dev/null +++ b/edge-proxy/railway.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://railway.app/railway.schema.json", + "build": { "builder": "NIXPACKS" }, + "deploy": { "startCommand": "node server.js", "restartPolicyType": "ON_FAILURE" } +} diff --git a/edge-proxy/server.js b/edge-proxy/server.js new file mode 100644 index 000000000..08a715704 --- /dev/null +++ b/edge-proxy/server.js @@ -0,0 +1,81 @@ +// WEVAL Edge Proxy — Sovereign AI Router +// Deploys on Railway (free $5) or Fly.io (free 3 VMs) +const http = require('http'); +const https = require('https'); + +const PORT = process.env.PORT || 3000; +const WEVAL_API = 'https://weval-consulting.com'; + +const PROVIDERS = { + groq: { url: 'https://api.groq.com/openai/v1/chat/completions', model: 'llama-3.3-70b-versatile' }, + cf: { url: 'https://api.cloudflare.com/client/v4/accounts/d3d50d5b6fb372afed8d7a8e4b16dd10/ai/run/@cf/meta/llama-3.1-8b-instruct' }, + cfdeep: { url: 'https://api.cloudflare.com/client/v4/accounts/d3d50d5b6fb372afed8d7a8e4b16dd10/ai/run/@cf/deepseek-ai/deepseek-r1-distill-qwen-32b' }, + gemini: { url: 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent' }, +}; + +function fetch(url, opts) { + return new Promise((resolve, reject) => { + const u = new URL(url); + const mod = u.protocol === 'https:' ? https : http; + const req = mod.request(u, { method: opts.method || 'GET', headers: opts.headers || {} }, res => { + let d = ''; + res.on('data', c => d += c); + res.on('end', () => resolve({ status: res.statusCode, body: d })); + }); + req.on('error', reject); + if (opts.body) req.write(opts.body); + req.end(); + }); +} + +const server = http.createServer(async (req, res) => { + res.setHeader('Access-Control-Allow-Origin', '*'); + res.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS'); + res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); + if (req.method === 'OPTIONS') { res.writeHead(200); return res.end(); } + + // Health check + if (req.url === '/' || req.url === '/health') { + res.writeHead(200, { 'Content-Type': 'application/json' }); + return res.end(JSON.stringify({ status: 'ok', service: 'WEVAL Edge Proxy', providers: Object.keys(PROVIDERS), uptime: process.uptime() })); + } + + // Chat endpoint + if (req.url === '/chat' && req.method === 'POST') { + let body = ''; + req.on('data', c => body += c); + req.on('end', async () => { + try { + const { message, provider } = JSON.parse(body); + if (!message) { res.writeHead(400); return res.end(JSON.stringify({ error: 'message required' })); } + // Proxy to WEVAL chatbot + const r = await fetch(WEVAL_API + '/api/weval-ia-fast.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ message, mode: 'fast' }) + }); + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(r.body); + } catch (e) { + res.writeHead(500); res.end(JSON.stringify({ error: e.message })); + } + }); + return; + } + + // Proxy to WEVAL API + if (req.url.startsWith('/api/')) { + try { + const r = await fetch(WEVAL_API + req.url, { method: req.method, headers: { 'Content-Type': 'application/json' } }); + res.writeHead(r.status, { 'Content-Type': 'application/json' }); + res.end(r.body); + } catch (e) { + res.writeHead(502); res.end(JSON.stringify({ error: 'upstream error' })); + } + return; + } + + res.writeHead(404); res.end(JSON.stringify({ error: 'not found' })); +}); + +server.listen(PORT, () => console.log(`WEVAL Edge Proxy running on :${PORT}`));