|
const express = require('express'); |
|
const bodyParser = require('body-parser'); |
|
const { exec } = require('child_process'); |
|
|
|
|
|
const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); |
|
|
|
const app = express(); |
|
const port = 7860; |
|
|
|
app.use(bodyParser.json()); |
|
app.use(bodyParser.urlencoded({ extended: true })); |
|
|
|
app.get("/", (req, res) => { |
|
res.set('Content-Type', 'text/plain'); |
|
res.send(`βοΈ Sunny API Server |
|
|
|
> You're using this server to test or eval code with Sunny! |
|
|
|
Supported models: |
|
- sunny: Run Node.js code |
|
- sunny-shell: Run real shell commands |
|
- sunny-plus: Get long-form code explanations via text.pollinations.ai |
|
|
|
π Educational use only. |
|
`); |
|
}); |
|
|
|
|
|
app.get("/models", (req, res) => { |
|
res.json({ |
|
object: "list", |
|
data: [ |
|
{ |
|
id: "sunny", |
|
object: "model", |
|
owned_by: "sunny-dev", |
|
created: Date.now() |
|
}, |
|
{ |
|
id: "sunny-shell", |
|
object: "model", |
|
owned_by: "sunny-dev", |
|
created: Date.now() |
|
}, |
|
{ |
|
id: "sunny-plus", |
|
object: "model", |
|
owned_by: "sunny-dev", |
|
created: Date.now() |
|
} |
|
] |
|
}); |
|
}); |
|
|
|
|
|
app.post("/chat/completions", async (req, res) => { |
|
const model = req.body.model || "sunny"; |
|
const messages = req.body.messages || []; |
|
|
|
const outputs = []; |
|
const logs = []; |
|
let totalPromptTokens = 0; |
|
|
|
for (const msg of messages) { |
|
const inputCode = msg.content || ""; |
|
const promptTokens = inputCode.split(/\s+/).length; |
|
totalPromptTokens += promptTokens; |
|
|
|
try { |
|
if (model === "sunny-shell") { |
|
|
|
const result = await new Promise((resolve) => { |
|
exec(inputCode, { timeout: 10000 }, (err, stdout, stderr) => { |
|
if (err) return resolve(`Shell Error: ${stderr || err.message}`); |
|
resolve(stdout || "No output from shell."); |
|
}); |
|
}); |
|
outputs.push(result.trim()); |
|
logs.push("Executed Shell: " + inputCode); |
|
} |
|
|
|
else if (model === "sunny-plus") { |
|
|
|
const pollinationURL = `https://text.pollinations.ai/${encodeURIComponent("Explain this code: " + inputCode)}`; |
|
const response = await fetch(pollinationURL); |
|
const explanation = await response.text(); |
|
outputs.push(explanation.trim()); |
|
logs.push("Fetched explanation via Pollinations."); |
|
} |
|
|
|
else { |
|
|
|
const consoleCapture = []; |
|
const customConsole = { |
|
log: (...args) => consoleCapture.push(args.join(" ")), |
|
error: (...args) => consoleCapture.push("ERROR: " + args.join(" ")) |
|
}; |
|
|
|
const wrappedCode = ` |
|
(async () => { |
|
let result; |
|
try { |
|
const console = customConsole; |
|
result = await (async () => { ${inputCode} })(); |
|
if (result !== undefined) console.log(result); |
|
} catch (e) { |
|
console.error("Runtime Error:", e.message); |
|
} |
|
})(); |
|
`; |
|
eval(wrappedCode); |
|
outputs.push(consoleCapture.join("\n") || "Execution Finished."); |
|
logs.push("NodeJS evaluated."); |
|
} |
|
} catch (err) { |
|
outputs.push("Execution Error: " + err.message); |
|
logs.push("Caught Error: " + err.message); |
|
} |
|
} |
|
|
|
const outputText = outputs.join("\n\n"); |
|
const completionTokens = outputText.split(/\s+/).length; |
|
|
|
res.json({ |
|
id: "chatcmpl-" + Math.random().toString(36).substring(2, 10), |
|
object: "chat.completion", |
|
created: Math.floor(Date.now() / 1000), |
|
model, |
|
choices: [ |
|
{ |
|
index: 0, |
|
message: { |
|
role: "assistant", |
|
content: outputText |
|
}, |
|
finish_reason: "stop" |
|
} |
|
], |
|
usage: { |
|
prompt_tokens: totalPromptTokens, |
|
completion_tokens: completionTokens, |
|
total_tokens: totalPromptTokens + completionTokens |
|
}, |
|
logs |
|
}); |
|
}); |
|
|
|
|
|
app.post("/end-of-service", (req, res) => { |
|
res.send("End of service. Rest well!"); |
|
}); |
|
|
|
app.listen(port, () => { |
|
console.log(`Sunny server running on port ${port}`); |
|
}); |
|
|