File size: 4,309 Bytes
d10a0b0
33115b6
 
 
e9cac85
 
 
d10a0b0
1a7bc8e
956ccbc
d10a0b0
68ceccd
 
 
 
33115b6
68ceccd
33115b6
68ceccd
33115b6
 
 
 
68ceccd
33115b6
68ceccd
 
 
33115b6
68ceccd
33115b6
68ceccd
 
 
 
 
 
33115b6
 
 
 
 
 
 
68ceccd
 
33115b6
68ceccd
 
33115b6
68ceccd
 
 
 
d10a0b0
33115b6
956ccbc
33115b6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
956ccbc
 
33115b6
 
956ccbc
 
33115b6
956ccbc
 
33115b6
956ccbc
80b5887
956ccbc
 
 
33115b6
80b5887
956ccbc
d10a0b0
956ccbc
 
33115b6
956ccbc
33115b6
 
 
956ccbc
 
 
e9cac85
 
 
 
 
956ccbc
33115b6
956ccbc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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}`);
});