Sunny / index.js
katsukiai's picture
Update index.js
e9cac85 verified
const express = require('express');
const bodyParser = require('body-parser');
const { exec } = require('child_process');
// Ensure fetch is available in Node.js
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.
`);
});
// Models endpoint
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()
}
]
});
});
// Chat/completions endpoint
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") {
// Shell execution
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") {
// Pollinations AI explanation
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 {
// Default NodeJS eval
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
});
});
// End of service when the user is tired or pauses
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}`);
});