ScottzillaSystems commited on
Commit
6d4cef9
·
verified ·
1 Parent(s): e254f55

UX v6.1: Internal agent bypass + response caching + graceful degradation

Browse files
Files changed (1) hide show
  1. server.mjs +173 -83
server.mjs CHANGED
@@ -11,6 +11,35 @@ const PORT = 11434;
11
  const HF_TOKEN = process.env.HF_TOKEN || process.env.OPENAI_API_KEY || "";
12
  const PAYMENTS_URL = "https://scottzillasystems-scottzilla-payments.hf.space";
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  // ─── Load model catalog ──────────────────────────────────────────────────────
15
  const catalog = JSON.parse(readFileSync("models.json", "utf-8"));
16
  const models = catalog.models;
@@ -27,46 +56,81 @@ function resolveModel(name) {
27
  }
28
 
29
  function routeByCapability(messages) {
30
- const text = messages.map((m) => m.content).join(" ").toLowerCase();
31
  if (/\b(image|picture|photo|draw|edit image|generate image)\b/.test(text))
32
  return resolveModel("qwen3-vl-8b-abliterated") || resolveModel("qwen3.5-9b");
33
- if (/\b(code|python|javascript|function|debug|program|script)\b/.test(text))
34
  return resolveModel("qwen3-coder-abliterated");
35
- if (/\b(uncensor|abliterat|jailbreak|unrestrict|nsfw)\b/.test(text))
36
  return resolveModel("qwen3.6-27b-abliterated");
37
- if (/\b(think|reason|math|logic|proof|step.by.step)\b/.test(text))
38
  return resolveModel("qwen3.5-40b-uncensored");
39
- if (/\b(creative|story|roleplay|write|fiction|narrative)\b/.test(text))
40
  return resolveModel("cydonia-24b");
 
 
41
  return resolveModel("qwen3.5-9b");
42
  }
43
 
44
- // ─── Payment verification middleware ─────────────────────────────────────────
45
  let freeUsageToday = new Map();
46
 
47
  async function verifyApiKey(key) {
 
 
 
 
 
48
  try {
49
- const resp = await fetch(`${PAYMENTS_URL}/api/keys/verify/${key}`);
50
  if (!resp.ok) return null;
51
- return await resp.json();
 
 
52
  } catch { return null; }
53
  }
54
 
55
  async function recordUsage(key, model) {
56
  try {
57
- await fetch(`${PAYMENTS_URL}/api/usage/record`, {
58
  method: "POST",
59
  headers: { "Content-Type": "application/json" },
60
  body: JSON.stringify({ api_key: key, model }),
61
- });
 
62
  } catch {}
63
  }
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  async function authMiddleware(req, res, next) {
 
 
 
 
 
 
 
66
  const authHeader = req.headers.authorization || req.headers["x-api-key"] || "";
67
  const key = authHeader.replace(/^Bearer\s+/i, "").trim();
68
 
69
- if (!key || key === HF_TOKEN || key === "sk-free-tier") {
 
70
  const ip = req.ip || req.headers["x-forwarded-for"] || "unknown";
71
  const today = new Date().toISOString().split("T")[0];
72
  const usageKey = `${ip}:${today}`;
@@ -83,9 +147,10 @@ async function authMiddleware(req, res, next) {
83
  return next();
84
  }
85
 
 
86
  const keyData = await verifyApiKey(key);
87
  if (!keyData || !keyData.valid) {
88
- // If payment server is down, allow through with basic access
89
  req.tier = "basic";
90
  req.allowedModels = ["all"];
91
  return next();
@@ -103,87 +168,105 @@ async function authMiddleware(req, res, next) {
103
  next();
104
  }
105
 
106
- // ─── HF Router proxy ────────────────────────────────────────────────────────
107
  async function hfChat(routerModel, messages, stream = false, params = {}) {
108
  const body = JSON.stringify({
109
  model: routerModel, messages, stream,
110
  max_tokens: params.max_tokens || 2048,
111
- temperature: params.temperature || 0.7,
112
  top_p: params.top_p || 0.95,
113
  });
114
- return new Promise((resolve, reject) => {
 
115
  const req = https.request({
116
  hostname: "router.huggingface.co", path: "/v1/chat/completions", method: "POST",
117
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${HF_TOKEN}`, "Content-Length": Buffer.byteLength(body) },
 
118
  }, (res) => {
119
  if (stream) return resolve(res);
120
  let data = ""; res.on("data", (c) => data += c);
121
  res.on("end", () => { try { resolve(JSON.parse(data)); } catch { resolve({ error: data }); } });
122
  });
123
- req.on("error", reject); req.end(body);
 
 
124
  });
 
 
 
 
 
 
 
125
  }
126
 
127
- // ─── HF Embeddings proxy ────────────────────────────────────────────────────
128
- async function hfEmbeddings(input, model = "sentence-transformers/all-MiniLM-L6-v2") {
129
  const texts = Array.isArray(input) ? input : [input];
130
  const body = JSON.stringify({ inputs: texts });
131
  return new Promise((resolve, reject) => {
132
  const req = https.request({
133
- hostname: "router.huggingface.co", path: `/pipeline/feature-extraction/${model}`,
 
134
  method: "POST",
135
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${HF_TOKEN}`, "Content-Length": Buffer.byteLength(body) },
 
136
  }, (res) => {
137
  let data = ""; res.on("data", (c) => data += c);
138
  res.on("end", () => { try { resolve(JSON.parse(data)); } catch { resolve(null); } });
139
  });
140
- req.on("error", reject); req.end(body);
 
 
141
  });
142
  }
143
 
144
- // Simple local embedding fallback (hash-based, 384-dim)
145
  function localEmbed(text) {
146
  const dim = 384;
147
  const embedding = new Array(dim).fill(0);
148
- for (let i = 0; i < text.length; i++) {
149
- embedding[i % dim] += text.charCodeAt(i) / 256.0;
 
 
 
 
 
 
 
150
  }
151
  const norm = Math.sqrt(embedding.reduce((s, v) => s + v * v, 0)) || 1;
152
  return embedding.map(v => v / norm);
153
  }
154
 
155
- // ─── Public endpoints (no auth) ─────────────────────���────────────────────────
156
  app.get("/", (req, res) => {
157
  res.json({
158
- status: "Scottzilla Gateway ⚡ operational",
159
- version: "6.0",
 
160
  models: models.length,
 
 
 
 
 
 
 
 
 
161
  pricing: PAYMENTS_URL,
162
- endpoints: [
163
- "GET /api/tags, /v1/models — list models",
164
- "POST /api/chat, /v1/chat/completions — chat",
165
- "POST /v1/embeddings — text embeddings",
166
- "GET /api/library — full catalog",
167
- "GET /api/route?q=... — smart route preview",
168
- "GET /health — health check",
169
- ],
170
- free_tier: "25 requests/day on chatgpt-5 — no key needed",
171
- agent_zero_spaces: [
172
- "https://huggingface.co/spaces/ScottzillaSystems/agent-zero",
173
- "https://huggingface.co/spaces/ScottzillaSystems/agent-zero-pentesting",
174
- "https://huggingface.co/spaces/ScottzillaSystems/agent-zero-finops",
175
- "https://huggingface.co/spaces/ScottzillaSystems/agent-zero-adult-entertainment",
176
- ],
177
  });
178
  });
179
 
180
  app.get("/health", (req, res) => {
181
- res.json({ status: "healthy", uptime: process.uptime(), models: models.length, timestamp: new Date().toISOString() });
182
  });
183
 
184
  app.get("/api/tags", (req, res) => {
185
  res.json({ models: models.map((m) => ({
186
- name: m.alias, model: m.alias, modified_at: new Date().toISOString(), size: (m.size_gb || 0) * 1e9, digest: m.hf_id,
 
187
  details: { parent_model: m.hf_id, format: m.arch, family: m.arch, parameter_size: m.params || "unknown" },
188
  }))});
189
  });
@@ -194,7 +277,6 @@ app.get("/v1/models", (req, res) => {
194
  id: m.alias, object: "model", created: Math.floor(Date.now() / 1000), owned_by: "ScottzillaSystems",
195
  hf_id: m.hf_id, capabilities: m.capabilities, params: m.params,
196
  })),
197
- // Embedding model entry
198
  { id: "text-embedding-3-small", object: "model", created: Math.floor(Date.now() / 1000), owned_by: "ScottzillaSystems", type: "embedding" },
199
  ]});
200
  });
@@ -204,26 +286,26 @@ app.get("/api/library", (req, res) => res.json(catalog));
204
  app.get("/api/route", (req, res) => {
205
  const q = req.query.q || "";
206
  const pick = routeByCapability([{ role: "user", content: q }]);
207
- res.json({ query: q, routed_to: pick ? { alias: pick.alias, name: pick.name, hf_id: pick.hf_id, capabilities: pick.capabilities } : null });
208
  });
209
 
210
  app.post("/api/show", (req, res) => {
211
  const entry = resolveModel(req.body.name || req.body.model);
212
  if (!entry) return res.status(404).json({ error: "model not found" });
213
- res.json({
214
- modelfile: `# ${entry.name}\nFROM ${entry.hf_id}\nPARAMETER temperature 0.7`,
215
- parameters: "temperature 0.7\ntop_p 0.95", template: "{{ .System }}\n{{ .Prompt }}",
216
- details: { parent_model: entry.hf_id, format: entry.arch, family: entry.arch, parameter_size: entry.params || "unknown", capabilities: entry.capabilities },
217
- });
218
  });
219
 
220
- // ─── Embeddings endpoint (for Agent Zero memory/RAG) ─────────────────────────
221
  app.post("/v1/embeddings", authMiddleware, async (req, res) => {
222
  try {
223
  const { input, model } = req.body;
224
  const texts = Array.isArray(input) ? input : [input];
225
 
226
- // Try HF inference API first
 
 
 
 
227
  let embeddings;
228
  try {
229
  const hfResult = await hfEmbeddings(texts);
@@ -232,37 +314,34 @@ app.post("/v1/embeddings", authMiddleware, async (req, res) => {
232
  }
233
  } catch {}
234
 
235
- // Fallback to local hash-based embeddings
236
  if (!embeddings) {
237
  embeddings = texts.map(t => localEmbed(typeof t === "string" ? t : JSON.stringify(t)));
238
  }
239
 
240
- res.json({
241
  object: "list",
242
  data: embeddings.map((emb, i) => ({
243
- object: "embedding",
244
- index: i,
245
- embedding: Array.isArray(emb[0]) ? emb[0] : emb, // Handle nested arrays from HF
246
  })),
247
  model: model || "text-embedding-3-small",
248
  usage: { prompt_tokens: texts.join("").length, total_tokens: texts.join("").length },
249
- });
 
 
 
250
  } catch (err) {
251
- // Even on error, return something usable
252
  const texts = Array.isArray(req.body?.input) ? req.body.input : [req.body?.input || ""];
253
  res.json({
254
  object: "list",
255
- data: texts.map((t, i) => ({
256
- object: "embedding", index: i,
257
- embedding: localEmbed(typeof t === "string" ? t : ""),
258
- })),
259
- model: req.body?.model || "text-embedding-3-small",
260
  usage: { prompt_tokens: 0, total_tokens: 0 },
261
  });
262
  }
263
  });
264
 
265
- // ─── Auth-gated chat endpoints ───────────────────────────────────────────────
266
  app.post("/api/chat", authMiddleware, async (req, res) => {
267
  try {
268
  const { model: modelName, messages, options } = req.body;
@@ -270,7 +349,7 @@ app.post("/api/chat", authMiddleware, async (req, res) => {
270
  if (!entry) return res.status(404).json({ error: `Model not found: ${modelName}` });
271
 
272
  if (req.tier === "free" && !req.allowedModels.includes(entry.alias) && !req.allowedModels.includes("all")) {
273
- return res.status(403).json({ error: `${entry.name} requires a paid plan. Free tier allows: ${req.allowedModels.join(", ")}`, upgrade: PAYMENTS_URL });
274
  }
275
 
276
  const routerModel = entry.router_model || "Qwen/Qwen3.5-9B";
@@ -279,9 +358,8 @@ app.post("/api/chat", authMiddleware, async (req, res) => {
279
 
280
  if (req.apiKey) recordUsage(req.apiKey, entry.alias);
281
 
282
- res.json({ model: entry.alias, created_at: new Date().toISOString(), message: { role: "assistant", content }, done: true,
283
- _meta: { hf_id: entry.hf_id, router_model: routerModel, tier: req.tier } });
284
- } catch (err) { res.status(500).json({ error: err.message }); }
285
  });
286
 
287
  app.post("/api/generate", authMiddleware, async (req, res) => {
@@ -300,7 +378,7 @@ app.post("/api/generate", authMiddleware, async (req, res) => {
300
  if (req.apiKey) recordUsage(req.apiKey, entry.alias);
301
 
302
  res.json({ model: entry.alias, created_at: new Date().toISOString(), response: result.choices?.[0]?.message?.content || "", done: true });
303
- } catch (err) { res.status(500).json({ error: err.message }); }
304
  });
305
 
306
  app.post("/v1/chat/completions", authMiddleware, async (req, res) => {
@@ -310,7 +388,7 @@ app.post("/v1/chat/completions", authMiddleware, async (req, res) => {
310
  if (!entry) return res.status(404).json({ error: { message: `Model not found: ${modelName}`, type: "invalid_request_error" } });
311
 
312
  if (req.tier === "free" && !req.allowedModels.includes(entry.alias) && !req.allowedModels.includes("all")) {
313
- return res.status(403).json({ error: { message: `${entry.name} requires a paid plan. Upgrade at ${PAYMENTS_URL}`, type: "insufficient_quota" } });
314
  }
315
 
316
  const routerModel = entry.router_model || "Qwen/Qwen3.5-9B";
@@ -318,32 +396,44 @@ app.post("/v1/chat/completions", authMiddleware, async (req, res) => {
318
  if (stream) {
319
  res.setHeader("Content-Type", "text/event-stream");
320
  res.setHeader("Cache-Control", "no-cache");
321
- const upstream = await hfChat(routerModel, messages, true, { temperature, max_tokens, top_p });
322
- upstream.on("data", (chunk) => res.write(chunk));
323
- upstream.on("end", () => { if (req.apiKey) recordUsage(req.apiKey, entry.alias); res.end(); });
324
- upstream.on("error", () => res.end());
 
 
 
 
 
 
325
  return;
326
  }
327
 
328
  const result = await hfChat(routerModel, messages, false, { temperature, max_tokens, top_p });
329
  if (req.apiKey) recordUsage(req.apiKey, entry.alias);
330
 
331
- res.json({ ...result, model: entry.alias, _scottzilla: { hf_id: entry.hf_id, router_model: routerModel, tier: req.tier, capabilities: entry.capabilities } });
332
- } catch (err) { res.status(500).json({ error: { message: err.message, type: "server_error" } }); }
 
 
 
 
 
 
 
 
333
  });
334
 
335
- // ─── Cleanup old free tier tracking daily ────────────────────────────────────
336
  setInterval(() => {
337
  const today = new Date().toISOString().split("T")[0];
338
  for (const [key] of freeUsageToday) {
339
  if (!key.endsWith(`:${today}`)) freeUsageToday.delete(key);
340
  }
341
- }, 3600000); // every hour
342
 
343
  // ─── Start ───────────────────────────────────────────────────────────────────
344
  app.listen(PORT, "0.0.0.0", () => {
345
- console.log(`⚡ Scottzilla Gateway v6.0 listening on :${PORT}`);
346
- console.log(` ${models.length} models | Embeddings: | Payments: ${PAYMENTS_URL}`);
347
- console.log(` Free tier: 25 req/day on chatgpt-5 + embeddings (no key needed)`);
348
- console.log(` Agent Zero Spaces: 4 connected`);
349
  });
 
11
  const HF_TOKEN = process.env.HF_TOKEN || process.env.OPENAI_API_KEY || "";
12
  const PAYMENTS_URL = "https://scottzillasystems-scottzilla-payments.hf.space";
13
 
14
+ // ─── Internal agent keys (bypass rate limiting for our own Spaces) ───────────
15
+ // Agent Zero Spaces authenticate with HF_TOKEN — same token means internal
16
+ const INTERNAL_ORIGINS = new Set([
17
+ "scottzillasystems-agent-zero.hf.space",
18
+ "scottzillasystems-agent-zero-pentesting.hf.space",
19
+ "scottzillasystems-agent-zero-finops.hf.space",
20
+ "scottzillasystems-agent-zero-adult-entertainment.hf.space",
21
+ ]);
22
+
23
+ // ─── Response cache (LRU, 5-min TTL) ────────────────────────────────────────
24
+ const cache = new Map();
25
+ const CACHE_TTL = 300000; // 5 min
26
+ const CACHE_MAX = 200;
27
+
28
+ function cacheGet(key) {
29
+ const entry = cache.get(key);
30
+ if (!entry) return null;
31
+ if (Date.now() - entry.ts > CACHE_TTL) { cache.delete(key); return null; }
32
+ return entry.value;
33
+ }
34
+
35
+ function cacheSet(key, value) {
36
+ if (cache.size >= CACHE_MAX) {
37
+ const oldest = cache.keys().next().value;
38
+ cache.delete(oldest);
39
+ }
40
+ cache.set(key, { value, ts: Date.now() });
41
+ }
42
+
43
  // ─── Load model catalog ──────────────────────────────────────────────────────
44
  const catalog = JSON.parse(readFileSync("models.json", "utf-8"));
45
  const models = catalog.models;
 
56
  }
57
 
58
  function routeByCapability(messages) {
59
+ const text = messages.map((m) => m.content || "").join(" ").toLowerCase();
60
  if (/\b(image|picture|photo|draw|edit image|generate image)\b/.test(text))
61
  return resolveModel("qwen3-vl-8b-abliterated") || resolveModel("qwen3.5-9b");
62
+ if (/\b(code|python|javascript|function|debug|program|script|sql|api)\b/.test(text))
63
  return resolveModel("qwen3-coder-abliterated");
64
+ if (/\b(uncensor|abliterat|jailbreak|unrestrict|nsfw|explicit)\b/.test(text))
65
  return resolveModel("qwen3.6-27b-abliterated");
66
+ if (/\b(think|reason|math|logic|proof|step.by.step|analyze|complex)\b/.test(text))
67
  return resolveModel("qwen3.5-40b-uncensored");
68
+ if (/\b(creative|story|roleplay|write|fiction|narrative|poem|essay)\b/.test(text))
69
  return resolveModel("cydonia-24b");
70
+ if (/\b(hack|exploit|vuln|pentest|nmap|security|attack|scan)\b/.test(text))
71
+ return resolveModel("qwen3.6-27b-abliterated");
72
  return resolveModel("qwen3.5-9b");
73
  }
74
 
75
+ // ─── Auth middleware with internal agent bypass ──────────────────────────────
76
  let freeUsageToday = new Map();
77
 
78
  async function verifyApiKey(key) {
79
+ // Cache key verification (avoid hammering payments server)
80
+ const cacheKey = `auth:${key}`;
81
+ const cached = cacheGet(cacheKey);
82
+ if (cached) return cached;
83
+
84
  try {
85
+ const resp = await fetch(`${PAYMENTS_URL}/api/keys/verify/${key}`, { signal: AbortSignal.timeout(5000) });
86
  if (!resp.ok) return null;
87
+ const data = await resp.json();
88
+ cacheSet(cacheKey, data);
89
+ return data;
90
  } catch { return null; }
91
  }
92
 
93
  async function recordUsage(key, model) {
94
  try {
95
+ fetch(`${PAYMENTS_URL}/api/usage/record`, {
96
  method: "POST",
97
  headers: { "Content-Type": "application/json" },
98
  body: JSON.stringify({ api_key: key, model }),
99
+ signal: AbortSignal.timeout(3000),
100
+ }).catch(() => {});
101
  } catch {}
102
  }
103
 
104
+ function isInternalAgent(req) {
105
+ // Check if request comes from our own Agent Zero Spaces
106
+ const origin = (req.headers.origin || req.headers.referer || "").toLowerCase();
107
+ const host = (req.headers["x-forwarded-host"] || "").toLowerCase();
108
+
109
+ for (const internal of INTERNAL_ORIGINS) {
110
+ if (origin.includes(internal) || host.includes(internal)) return true;
111
+ }
112
+
113
+ // Also check if they're using HF_TOKEN as auth (our own Spaces do this)
114
+ const authHeader = req.headers.authorization || "";
115
+ const key = authHeader.replace(/^Bearer\s+/i, "").trim();
116
+ if (key === HF_TOKEN && HF_TOKEN.length > 10) return true;
117
+
118
+ return false;
119
+ }
120
+
121
  async function authMiddleware(req, res, next) {
122
+ // ─── INTERNAL AGENT BYPASS: Our own Spaces get unlimited access ───────
123
+ if (isInternalAgent(req)) {
124
+ req.tier = "internal";
125
+ req.allowedModels = ["all"];
126
+ return next();
127
+ }
128
+
129
  const authHeader = req.headers.authorization || req.headers["x-api-key"] || "";
130
  const key = authHeader.replace(/^Bearer\s+/i, "").trim();
131
 
132
+ // No key free tier
133
+ if (!key || key === "sk-free-tier") {
134
  const ip = req.ip || req.headers["x-forwarded-for"] || "unknown";
135
  const today = new Date().toISOString().split("T")[0];
136
  const usageKey = `${ip}:${today}`;
 
147
  return next();
148
  }
149
 
150
+ // Validate paid API key
151
  const keyData = await verifyApiKey(key);
152
  if (!keyData || !keyData.valid) {
153
+ // Payment server unreachable or key invalid graceful degradation
154
  req.tier = "basic";
155
  req.allowedModels = ["all"];
156
  return next();
 
168
  next();
169
  }
170
 
171
+ // ─── HF Router proxy with retry ─────────────────────────────────────────────
172
  async function hfChat(routerModel, messages, stream = false, params = {}) {
173
  const body = JSON.stringify({
174
  model: routerModel, messages, stream,
175
  max_tokens: params.max_tokens || 2048,
176
+ temperature: params.temperature ?? 0.7,
177
  top_p: params.top_p || 0.95,
178
  });
179
+
180
+ const attempt = () => new Promise((resolve, reject) => {
181
  const req = https.request({
182
  hostname: "router.huggingface.co", path: "/v1/chat/completions", method: "POST",
183
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${HF_TOKEN}`, "Content-Length": Buffer.byteLength(body) },
184
+ timeout: 60000,
185
  }, (res) => {
186
  if (stream) return resolve(res);
187
  let data = ""; res.on("data", (c) => data += c);
188
  res.on("end", () => { try { resolve(JSON.parse(data)); } catch { resolve({ error: data }); } });
189
  });
190
+ req.on("error", reject);
191
+ req.on("timeout", () => { req.destroy(); reject(new Error("timeout")); });
192
+ req.end(body);
193
  });
194
+
195
+ // Single retry on failure
196
+ try { return await attempt(); }
197
+ catch (e) {
198
+ await new Promise(r => setTimeout(r, 1000));
199
+ return await attempt();
200
+ }
201
  }
202
 
203
+ // ─── HF Embeddings with cache ───────────────────────────────────────────────
204
+ async function hfEmbeddings(input) {
205
  const texts = Array.isArray(input) ? input : [input];
206
  const body = JSON.stringify({ inputs: texts });
207
  return new Promise((resolve, reject) => {
208
  const req = https.request({
209
+ hostname: "router.huggingface.co",
210
+ path: "/pipeline/feature-extraction/sentence-transformers/all-MiniLM-L6-v2",
211
  method: "POST",
212
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${HF_TOKEN}`, "Content-Length": Buffer.byteLength(body) },
213
+ timeout: 15000,
214
  }, (res) => {
215
  let data = ""; res.on("data", (c) => data += c);
216
  res.on("end", () => { try { resolve(JSON.parse(data)); } catch { resolve(null); } });
217
  });
218
+ req.on("error", reject);
219
+ req.on("timeout", () => { req.destroy(); reject(new Error("timeout")); });
220
+ req.end(body);
221
  });
222
  }
223
 
224
+ // Deterministic local embedding fallback (384-dim, cosine-similarity compatible)
225
  function localEmbed(text) {
226
  const dim = 384;
227
  const embedding = new Array(dim).fill(0);
228
+ const str = (text || "").toLowerCase().trim();
229
+ // Use character n-gram hashing for better semantic signal
230
+ for (let i = 0; i < str.length; i++) {
231
+ const c = str.charCodeAt(i);
232
+ embedding[c % dim] += 1.0;
233
+ if (i + 1 < str.length) {
234
+ const bigram = (c * 31 + str.charCodeAt(i + 1)) % dim;
235
+ embedding[bigram] += 0.5;
236
+ }
237
  }
238
  const norm = Math.sqrt(embedding.reduce((s, v) => s + v * v, 0)) || 1;
239
  return embedding.map(v => v / norm);
240
  }
241
 
242
+ // ─── Public endpoints ────────────────────────────────────────────────────────
243
  app.get("/", (req, res) => {
244
  res.json({
245
+ status: "operational",
246
+ name: "Scottzilla Gateway",
247
+ version: "6.1",
248
  models: models.length,
249
+ uptime_s: Math.floor(process.uptime()),
250
+ endpoints: {
251
+ chat: "POST /v1/chat/completions",
252
+ embeddings: "POST /v1/embeddings",
253
+ models: "GET /v1/models",
254
+ route: "GET /api/route?q=...",
255
+ health: "GET /health",
256
+ },
257
+ free_tier: { limit: "25 req/day", models: ["chatgpt-5"], no_key_needed: true },
258
  pricing: PAYMENTS_URL,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  });
260
  });
261
 
262
  app.get("/health", (req, res) => {
263
+ res.json({ status: "healthy", uptime: process.uptime(), models: models.length, cache_size: cache.size, timestamp: new Date().toISOString() });
264
  });
265
 
266
  app.get("/api/tags", (req, res) => {
267
  res.json({ models: models.map((m) => ({
268
+ name: m.alias, model: m.alias, modified_at: new Date().toISOString(),
269
+ size: (m.size_gb || 0) * 1e9, digest: m.hf_id,
270
  details: { parent_model: m.hf_id, format: m.arch, family: m.arch, parameter_size: m.params || "unknown" },
271
  }))});
272
  });
 
277
  id: m.alias, object: "model", created: Math.floor(Date.now() / 1000), owned_by: "ScottzillaSystems",
278
  hf_id: m.hf_id, capabilities: m.capabilities, params: m.params,
279
  })),
 
280
  { id: "text-embedding-3-small", object: "model", created: Math.floor(Date.now() / 1000), owned_by: "ScottzillaSystems", type: "embedding" },
281
  ]});
282
  });
 
286
  app.get("/api/route", (req, res) => {
287
  const q = req.query.q || "";
288
  const pick = routeByCapability([{ role: "user", content: q }]);
289
+ res.json({ query: q, routed_to: pick ? { alias: pick.alias, name: pick.name, capabilities: pick.capabilities } : null });
290
  });
291
 
292
  app.post("/api/show", (req, res) => {
293
  const entry = resolveModel(req.body.name || req.body.model);
294
  if (!entry) return res.status(404).json({ error: "model not found" });
295
+ res.json({ details: { ...entry } });
 
 
 
 
296
  });
297
 
298
+ // ─── Embeddings ──────────────────────────────────────────────────────────────
299
  app.post("/v1/embeddings", authMiddleware, async (req, res) => {
300
  try {
301
  const { input, model } = req.body;
302
  const texts = Array.isArray(input) ? input : [input];
303
 
304
+ // Check cache first
305
+ const cacheKey = `emb:${texts.join("|").slice(0, 200)}`;
306
+ const cached = cacheGet(cacheKey);
307
+ if (cached) return res.json(cached);
308
+
309
  let embeddings;
310
  try {
311
  const hfResult = await hfEmbeddings(texts);
 
314
  }
315
  } catch {}
316
 
 
317
  if (!embeddings) {
318
  embeddings = texts.map(t => localEmbed(typeof t === "string" ? t : JSON.stringify(t)));
319
  }
320
 
321
+ const response = {
322
  object: "list",
323
  data: embeddings.map((emb, i) => ({
324
+ object: "embedding", index: i,
325
+ embedding: Array.isArray(emb[0]) ? emb[0] : emb,
 
326
  })),
327
  model: model || "text-embedding-3-small",
328
  usage: { prompt_tokens: texts.join("").length, total_tokens: texts.join("").length },
329
+ };
330
+
331
+ cacheSet(cacheKey, response);
332
+ res.json(response);
333
  } catch (err) {
 
334
  const texts = Array.isArray(req.body?.input) ? req.body.input : [req.body?.input || ""];
335
  res.json({
336
  object: "list",
337
+ data: texts.map((t, i) => ({ object: "embedding", index: i, embedding: localEmbed(t || "") })),
338
+ model: "text-embedding-3-small",
 
 
 
339
  usage: { prompt_tokens: 0, total_tokens: 0 },
340
  });
341
  }
342
  });
343
 
344
+ // ─── Chat endpoints ──────────────────────────────────────────────────────────
345
  app.post("/api/chat", authMiddleware, async (req, res) => {
346
  try {
347
  const { model: modelName, messages, options } = req.body;
 
349
  if (!entry) return res.status(404).json({ error: `Model not found: ${modelName}` });
350
 
351
  if (req.tier === "free" && !req.allowedModels.includes(entry.alias) && !req.allowedModels.includes("all")) {
352
+ return res.status(403).json({ error: `${entry.name} requires a paid plan.`, upgrade: PAYMENTS_URL });
353
  }
354
 
355
  const routerModel = entry.router_model || "Qwen/Qwen3.5-9B";
 
358
 
359
  if (req.apiKey) recordUsage(req.apiKey, entry.alias);
360
 
361
+ res.json({ model: entry.alias, created_at: new Date().toISOString(), message: { role: "assistant", content }, done: true });
362
+ } catch (err) { res.status(502).json({ error: `Gateway error: ${err.message}. Retrying may help.` }); }
 
363
  });
364
 
365
  app.post("/api/generate", authMiddleware, async (req, res) => {
 
378
  if (req.apiKey) recordUsage(req.apiKey, entry.alias);
379
 
380
  res.json({ model: entry.alias, created_at: new Date().toISOString(), response: result.choices?.[0]?.message?.content || "", done: true });
381
+ } catch (err) { res.status(502).json({ error: err.message }); }
382
  });
383
 
384
  app.post("/v1/chat/completions", authMiddleware, async (req, res) => {
 
388
  if (!entry) return res.status(404).json({ error: { message: `Model not found: ${modelName}`, type: "invalid_request_error" } });
389
 
390
  if (req.tier === "free" && !req.allowedModels.includes(entry.alias) && !req.allowedModels.includes("all")) {
391
+ return res.status(403).json({ error: { message: `${entry.name} requires a paid plan.`, type: "insufficient_quota" } });
392
  }
393
 
394
  const routerModel = entry.router_model || "Qwen/Qwen3.5-9B";
 
396
  if (stream) {
397
  res.setHeader("Content-Type", "text/event-stream");
398
  res.setHeader("Cache-Control", "no-cache");
399
+ res.setHeader("Connection", "keep-alive");
400
+ try {
401
+ const upstream = await hfChat(routerModel, messages, true, { temperature, max_tokens, top_p });
402
+ upstream.on("data", (chunk) => res.write(chunk));
403
+ upstream.on("end", () => { if (req.apiKey) recordUsage(req.apiKey, entry.alias); res.end(); });
404
+ upstream.on("error", () => res.end());
405
+ } catch (e) {
406
+ res.write(`data: {"error":"${e.message}"}\n\n`);
407
+ res.end();
408
+ }
409
  return;
410
  }
411
 
412
  const result = await hfChat(routerModel, messages, false, { temperature, max_tokens, top_p });
413
  if (req.apiKey) recordUsage(req.apiKey, entry.alias);
414
 
415
+ // Return clean OpenAI-compatible response
416
+ res.json({
417
+ id: `chatcmpl-${Date.now()}`,
418
+ object: "chat.completion",
419
+ created: Math.floor(Date.now() / 1000),
420
+ model: entry.alias,
421
+ choices: result.choices || [{ index: 0, message: { role: "assistant", content: "" }, finish_reason: "stop" }],
422
+ usage: result.usage || { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },
423
+ });
424
+ } catch (err) { res.status(502).json({ error: { message: err.message, type: "server_error" } }); }
425
  });
426
 
427
+ // ─── Cleanup ─────────────────────────────────────────────────────────────────
428
  setInterval(() => {
429
  const today = new Date().toISOString().split("T")[0];
430
  for (const [key] of freeUsageToday) {
431
  if (!key.endsWith(`:${today}`)) freeUsageToday.delete(key);
432
  }
433
+ }, 3600000);
434
 
435
  // ─── Start ───────────────────────────────────────────────────────────────────
436
  app.listen(PORT, "0.0.0.0", () => {
437
+ console.log(`⚡ Scottzilla Gateway v6.1 | :${PORT} | ${models.length} models`);
438
+ console.log(` Internal agents: unlimited | Free tier: 25/day | Cache: active`);
 
 
439
  });