@mvkproject/nexus
Version:
Free AI SDK with API key (500 free daily requests). Access 25+ LLM models (GPT-4, Gemini, Llama, DeepSeek), generate images with 14+ models (Flux, Stable Diffusion), and integrate Akinator game - all completely free.
316 lines (255 loc) • 7.19 kB
JavaScript
const axios = require('axios');
class APIClient {
constructor(apiKey, baseURL = 'https://nexus.drexus.xyz') {
if (!apiKey) {
throw new Error('API key is required. Get your free API key at https://nexus.drexus.xyz');
}
this.apiKey = apiKey;
this.baseURL = baseURL;
this.client = axios.create({
baseURL: this.baseURL,
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
}
});
}
async request(method, endpoint, data = null, config = {}) {
try {
const response = await this.client.request({
method,
url: endpoint,
data,
...config
});
return response.data;
} catch (error) {
this.handleError(error);
}
}
handleError(error) {
if (error.response) {
const { status, data } = error.response;
const message = data?.message || data?.error || 'Unknown error occurred';
switch (status) {
case 400:
throw new Error(`Bad Request: ${message}`);
case 401:
throw new Error('Unauthorized: Invalid or missing API key');
case 403:
throw new Error('Forbidden: Access denied');
case 404:
throw new Error(`Not Found: ${message}`);
case 429:
throw new Error('Too Many Requests: Daily limit exceeded');
case 500:
throw new Error(`Server Error: ${message}`);
default:
throw new Error(`API Error (${status}): ${message}`);
}
} else if (error.request) {
throw new Error('Network Error: Unable to reach the Nexus API');
} else {
throw new Error(`Request Error: ${error.message}`);
}
}
get(endpoint, config) {
return this.request('GET', endpoint, null, config);
}
post(endpoint, data, config) {
return this.request('POST', endpoint, data, config);
}
delete(endpoint, config) {
return this.request('DELETE', endpoint, null, config);
}
}
class ImageAPI {
constructor(client) {
this.client = client;
}
async generate(options) {
const {
prompt,
model = 'flux',
width = 512,
height = 512
} = options;
if (!prompt) {
throw new Error('Prompt is required for image generation');
}
const data = {
prompt,
model,
width,
height
};
return await this.client.post('/v1/generate-image', data);
}
}
class TextAPI {
constructor(client) {
this.client = client;
}
async generate(options) {
const {
model,
prompt,
userid,
systemInstruction,
temperature = 1.0,
maxOutputTokens = 8192,
images,
stream = false
} = options;
if (!model) {
throw new Error('Model is required for text generation');
}
if (!prompt) {
throw new Error('Prompt is required for text generation');
}
if (stream) {
throw new Error('For streaming, use generateStream() method instead');
}
const data = {
model,
prompt,
temperature,
maxOutputTokens
};
if (userid) data.userid = userid;
if (systemInstruction) data.systemInstruction = systemInstruction;
if (images) data.images = images;
return await this.client.post('/v1/text/generate', data);
}
async generateStream(options, onChunk) {
const {
model,
prompt,
userid,
systemInstruction,
temperature = 1.0,
maxOutputTokens = 8192,
images
} = options;
if (!model) {
throw new Error('Model is required for text generation');
}
if (!prompt) {
throw new Error('Prompt is required for text generation');
}
if (typeof onChunk !== 'function') {
throw new Error('onChunk callback function is required for streaming');
}
const data = {
model,
prompt,
temperature,
maxOutputTokens,
stream: true
};
if (userid) data.userid = userid;
if (systemInstruction) data.systemInstruction = systemInstruction;
if (images) data.images = images;
try {
const response = await this.client.client.post('/v1/text/generate', data, {
responseType: 'stream'
});
return new Promise((resolve, reject) => {
let buffer = '';
response.data.on('data', (chunk) => {
buffer += chunk.toString();
const lines = buffer.split('\n');
buffer = lines.pop();
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6).trim();
if (data === '[DONE]') {
resolve();
return;
}
try {
const parsed = JSON.parse(data);
if (parsed.chunk) {
onChunk(parsed.chunk);
}
} catch (e) {
}
}
}
});
response.data.on('end', () => {
resolve();
});
response.data.on('error', (error) => {
reject(error);
});
});
} catch (error) {
this.client.handleError(error);
}
}
async clearHistory(userid) {
if (!userid) {
throw new Error('User ID is required to clear history');
}
return await this.client.delete(`/v1/text/history/${userid}`);
}
}
class AkinatorAPI {
constructor(client) {
this.client = client;
}
async start(options = {}) {
const { region = 'en', childMode = false } = options;
return await this.client.get(
`/v1/games/akinator/start?region=${region}&childMode=${childMode}`
);
}
async answer(gameId, answer) {
if (!gameId) {
throw new Error('Game ID is required');
}
const validAnswers = ['yes', 'no', 'dont-know', 'probably', 'probably-not'];
if (!validAnswers.includes(answer)) {
throw new Error(`Invalid answer. Must be one of: ${validAnswers.join(', ')}`);
}
return await this.client.get(
`/v1/games/akinator/answer/${gameId}?answer=${answer}`
);
}
async back(gameId) {
if (!gameId) {
throw new Error('Game ID is required');
}
return await this.client.get(`/v1/games/akinator/back/${gameId}`);
}
async progress(gameId) {
if (!gameId) {
throw new Error('Game ID is required');
}
return await this.client.get(`/v1/games/akinator/progress/${gameId}`);
}
async delete(gameId) {
if (!gameId) {
throw new Error('Game ID is required');
}
return await this.client.delete(`/v1/games/akinator/game/${gameId}`);
}
}
class NexusClient {
constructor(options) {
if (typeof options === 'string') {
options = { apiKey: options };
}
const { apiKey, baseURL } = options;
if (!apiKey) {
throw new Error('API key is required. Get your free API key at https://nexus.drexus.xyz');
}
this.client = new APIClient(apiKey, baseURL);
this.image = new ImageAPI(this.client);
this.text = new TextAPI(this.client);
this.akinator = new AkinatorAPI(this.client);
}
}
module.exports = { NexusClient };
module.exports.default = NexusClient;