katsukiai commited on
Commit
33115b6
Β·
verified Β·
1 Parent(s): 68ceccd

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +95 -67
index.js CHANGED
@@ -1,121 +1,149 @@
1
- /**
2
- * Sunny - OpenAI-like API Server for testing NodeJS code
3
- */
4
  const express = require('express');
 
 
 
 
5
  const app = express();
6
  const port = 7860;
7
- const bodyParser = require('body-parser');
8
- const vm = require('vm');
9
 
10
  app.use(bodyParser.json());
11
  app.use(bodyParser.urlencoded({ extended: true }));
12
 
13
- // Root endpoint
14
  app.get("/", (req, res) => {
15
  res.set('Content-Type', 'text/plain');
16
- res.send(`β˜€οΈ Sunny!
17
- > You're using this server to eval your code with Sunny!
18
 
19
- This server model only supports NodeJS. It doesn't generate text, only executes code for testing.
20
 
21
- πŸ›‚ For educational purposes only. Do not use this server for illegal activities.
 
 
 
22
 
23
- > Usage:
24
- - Use OpenWebUI:
25
- Administrators Settings > Connections > Add Connection (OpenAI)
26
- - Use h3 HF Spaces:
27
- https://huggingface.co/spaces/katsukiai/h3
28
  `);
29
  });
30
 
31
- // /models - Return the models
32
  app.get("/models", (req, res) => {
33
- res.set('Content-Type', 'application/json');
34
- res.send({
35
  object: "list",
36
  data: [
37
  {
38
  id: "sunny",
39
  object: "model",
40
- created: Math.floor(Date.now() / 1000),
41
  owned_by: "sunny-dev",
42
- permission: [],
43
- root: "sunny",
44
- parent: null
 
 
 
 
45
  },
46
  {
47
- id: "sunny-beta",
48
  object: "model",
49
- created: Math.floor(Date.now() / 1000),
50
  owned_by: "sunny-dev",
51
- permission: [],
52
- root: "sunny-beta",
53
- parent: null
54
  }
55
  ]
56
  });
57
  });
58
 
59
- // /chat/completions - Secure sandboxed code execution
60
  app.post("/chat/completions", async (req, res) => {
61
- const input = req.body?.messages?.[0]?.content || "";
62
- let output = '';
63
- let logs = [];
64
- let promptTokens = input.split(/\s+/).length; // Rough estimate of prompt tokens
65
-
66
- try {
67
- const sandbox = {
68
- console: {
69
- log: (...args) => logs.push(args.join(" "))
70
- },
71
- result: undefined
72
- };
73
-
74
- const context = vm.createContext(sandbox);
75
- const wrappedCode = `
76
- (async () => {
77
- try {
78
- result = await (async () => { ${input} })();
79
- } catch (e) {
80
- result = 'Runtime Error: ' + e.message;
81
- }
82
- })()
83
- `;
84
-
85
- const script = new vm.Script(wrappedCode);
86
-
87
- await script.runInContext(context, { timeout: 1000 });
88
-
89
- output = sandbox.result;
90
- } catch (err) {
91
- output = 'Execution Timeout or VM Error: ' + err.message;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  }
93
 
94
- let completionTokens = output.split(/\s+/).length; // Rough estimate of completion tokens
 
95
 
96
  res.json({
97
- id: "chatcmpl-" + Math.random().toString(36).substr(2, 9),
98
  object: "chat.completion",
99
  created: Math.floor(Date.now() / 1000),
100
- model: req.body.model || "sunny",
101
  choices: [
102
  {
103
  index: 0,
104
  message: {
105
  role: "assistant",
106
- content: output
107
  },
108
  finish_reason: "stop"
109
  }
110
  ],
111
  usage: {
112
- prompt_tokens: promptTokens,
113
  completion_tokens: completionTokens,
114
- total_tokens: promptTokens + completionTokens
115
- }
 
116
  });
117
  });
118
 
119
  app.listen(port, () => {
120
- console.log(`β˜€οΈ Sunny listening on port ${port}!`);
121
  });
 
 
 
 
1
  const express = require('express');
2
+ const bodyParser = require('body-parser');
3
+ const fetch = require('node-fetch');
4
+ const { exec } = require('child_process');
5
+
6
  const app = express();
7
  const port = 7860;
 
 
8
 
9
  app.use(bodyParser.json());
10
  app.use(bodyParser.urlencoded({ extended: true }));
11
 
 
12
  app.get("/", (req, res) => {
13
  res.set('Content-Type', 'text/plain');
14
+ res.send(`β˜€οΈ Sunny API Server
 
15
 
16
+ > You're using this server to test or eval code with Sunny!
17
 
18
+ Supported models:
19
+ - sunny: Run Node.js code
20
+ - sunny-shell: Run real shell commands
21
+ - sunny-plus: Get long-form code explanations via text.pollinations.ai
22
 
23
+ πŸ›‚ Educational use only.
 
 
 
 
24
  `);
25
  });
26
 
27
+ // Models endpoint
28
  app.get("/models", (req, res) => {
29
+ res.json({
 
30
  object: "list",
31
  data: [
32
  {
33
  id: "sunny",
34
  object: "model",
 
35
  owned_by: "sunny-dev",
36
+ created: Date.now()
37
+ },
38
+ {
39
+ id: "sunny-shell",
40
+ object: "model",
41
+ owned_by: "sunny-dev",
42
+ created: Date.now()
43
  },
44
  {
45
+ id: "sunny-plus",
46
  object: "model",
 
47
  owned_by: "sunny-dev",
48
+ created: Date.now()
 
 
49
  }
50
  ]
51
  });
52
  });
53
 
54
+ // Chat/completions endpoint
55
  app.post("/chat/completions", async (req, res) => {
56
+ const model = req.body.model || "sunny";
57
+ const messages = req.body.messages || [];
58
+
59
+ const outputs = [];
60
+ const logs = [];
61
+ let totalPromptTokens = 0;
62
+
63
+ for (const msg of messages) {
64
+ const inputCode = msg.content || "";
65
+ const promptTokens = inputCode.split(/\s+/).length;
66
+ totalPromptTokens += promptTokens;
67
+
68
+ try {
69
+ if (model === "sunny-shell") {
70
+ // Shell execution
71
+ const result = await new Promise((resolve) => {
72
+ exec(inputCode, { timeout: 10000 }, (err, stdout, stderr) => {
73
+ if (err) return resolve(`Shell Error: ${stderr || err.message}`);
74
+ resolve(stdout || "No output from shell.");
75
+ });
76
+ });
77
+ outputs.push(result.trim());
78
+ logs.push("Executed Shell: " + inputCode);
79
+ }
80
+
81
+ else if (model === "sunny-plus") {
82
+ // Pollinations AI explanation
83
+ const pollinationURL = `https://text.pollinations.ai/${encodeURIComponent("Explain this code: " + inputCode)}`;
84
+ const response = await fetch(pollinationURL);
85
+ const explanation = await response.text();
86
+ outputs.push(explanation.trim());
87
+ logs.push("Fetched explanation via Pollinations.");
88
+ }
89
+
90
+ else {
91
+ // Default NodeJS eval
92
+ const consoleCapture = [];
93
+ const customConsole = {
94
+ log: (...args) => consoleCapture.push(args.join(" ")),
95
+ error: (...args) => consoleCapture.push("ERROR: " + args.join(" "))
96
+ };
97
+
98
+ const wrappedCode = `
99
+ (async () => {
100
+ let result;
101
+ try {
102
+ const console = customConsole;
103
+ result = await (async () => { ${inputCode} })();
104
+ if (result !== undefined) console.log(result);
105
+ } catch (e) {
106
+ console.error("Runtime Error:", e.message);
107
+ }
108
+ })();
109
+ `;
110
+ eval(wrappedCode);
111
+ outputs.push(consoleCapture.join("\n") || "Execution Finished.");
112
+ logs.push("NodeJS evaluated.");
113
+ }
114
+ } catch (err) {
115
+ outputs.push("Execution Error: " + err.message);
116
+ logs.push("Caught Error: " + err.message);
117
+ }
118
  }
119
 
120
+ const outputText = outputs.join("\n\n");
121
+ const completionTokens = outputText.split(/\s+/).length;
122
 
123
  res.json({
124
+ id: "chatcmpl-" + Math.random().toString(36).substring(2, 10),
125
  object: "chat.completion",
126
  created: Math.floor(Date.now() / 1000),
127
+ model,
128
  choices: [
129
  {
130
  index: 0,
131
  message: {
132
  role: "assistant",
133
+ content: outputText
134
  },
135
  finish_reason: "stop"
136
  }
137
  ],
138
  usage: {
139
+ prompt_tokens: totalPromptTokens,
140
  completion_tokens: completionTokens,
141
+ total_tokens: totalPromptTokens + completionTokens
142
+ },
143
+ logs
144
  });
145
  });
146
 
147
  app.listen(port, () => {
148
+ console.log(`Sunny server running on port ${port}`);
149
  });