# uncloseai. Node.js Client A Node.js client library for interacting with vLLM, Ollama, and OpenAI-compatible APIs. ## Features - 🔍 **Automatic Model Discovery** - Discovers available models from configured endpoints - 💬 **Chat Completions** - Both streaming and non-streaming modes - 🎙️ **Text-to-Speech** - Generate audio from text with multiple voice options - 🔄 **Multiple Endpoints** - Support for multiple model and TTS endpoints - 🛡️ **Error Handling** - Comprehensive error handling with custom exceptions - 📦 **Zero Dependencies** - Uses only Node.js built-in modules (https, http, fs) ## Installation No external dependencies required! Just copy `uncloseai_lib.js` to your project: ```bash # Copy the library file cp uncloseai_lib.js your-project/ # Or use it directly node examples.js ``` ## Quick Start ```javascript const { uncloseai } = require('./uncloseai_lib'); // Initialize client (auto-discovers from environment variables) const client = new uncloseai(); // Non-streaming chat const response = await client.chat({ model: 'auto', messages: [{ role: 'user', content: 'Hello!' }] }); console.log(response.choices[0].message.content); // Streaming chat for await (const chunk of client.chatStream({ model: 'auto', messages: [{ role: 'user', content: 'Write a story' }] })) { const content = chunk.choices?.[0]?.delta?.content || ''; process.stdout.write(content); } ``` ## Configuration ### Environment Variables ```bash # Model endpoints (numbered 1-9999) export MODEL_ENDPOINT_1="https://hermes.ai.unturf.com/v1" export MODEL_ENDPOINT_2="https://qwen.ai.unturf.com/v1" # TTS endpoints (numbered 1-9999) export TTS_ENDPOINT_1="https://speech.ai.unturf.com/v1" ``` ### Programmatic Configuration ```javascript const client = new uncloseai({ endpoints: ['https://api.example.com/v1'], ttsEndpoints: ['https://tts.example.com/v1'], apiKey: 'your-api-key', // Optional timeout: 30000, // Request timeout in milliseconds debug: true // Enable debug logging }); ``` ## API Reference ### uncloseai. Client Main client class for interacting with AI APIs. #### `constructor(options)` Initialize the client. **Parameters:** - `endpoints` (Array, optional): Model endpoints (auto-discovers from env if not provided) - `ttsEndpoints` (Array, optional): TTS endpoints (auto-discovers from env if not provided) - `apiKey` (String, optional): API key for authentication - `timeout` (Number): Request timeout in milliseconds (default: 30000) - `debug` (Boolean): Enable debug logging (default: false) #### `async listModels()` List all discovered models with their metadata. **Returns:** - Array of objects with `id`, `endpoint`, and `max_tokens` **Example:** ```javascript const models = await client.listModels(); console.log(models); // [{ id: 'model-name', endpoint: 'https://...', max_tokens: 8192 }, ...] ``` #### `async chat(options)` Send a non-streaming chat completion request. **Parameters:** - `messages` (Array): Array of message objects with 'role' and 'content' - `model` (String): Model ID or 'auto' for first available (default: 'auto') - `maxTokens` (Number, optional): Maximum tokens to generate - `temperature` (Number): Sampling temperature 0-2 (default: 0.7) - `topP` (Number): Nucleus sampling parameter (default: 1.0) - Additional parameters passed to API **Returns:** - Chat completion response object **Throws:** - `ModelNotFoundError`: If model not found - `ConnectionError`: If request fails **Example:** ```javascript const response = await client.chat({ model: 'auto', messages: [ { role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: 'What is AI?' } ], maxTokens: 100 }); console.log(response.choices[0].message.content); ``` #### `async *chatStream(options)` Send a streaming chat completion request. **Parameters:** - Same as `chat()` **Yields:** - Chat completion chunk objects **Throws:** - `ModelNotFoundError`: If model not found - `StreamingError`: If streaming fails **Example:** ```javascript for await (const chunk of client.chatStream({ model: 'auto', messages: [{ role: 'user', content: 'Write a haiku' }] })) { const content = chunk.choices?.[0]?.delta?.content || ''; if (content) { process.stdout.write(content); } } ``` #### `async tts(options)` Generate speech from text. **Parameters:** - `text` (String): Text to convert to speech - `voice` (String): Voice to use - alloy, echo, fable, onyx, nova, shimmer (default: 'alloy') - `model` (String): TTS model - tts-1 or tts-1-hd (default: 'tts-1') - Additional parameters passed to API **Returns:** - Buffer containing audio data (MP3 format) **Throws:** - `ConnectionError`: If request fails - `uncloseaiError`: If no TTS endpoints available **Example:** ```javascript const audioData = await client.tts({ text: 'Hello from uncloseai.!', voice: 'alloy', model: 'tts-1' }); fs.writeFileSync('output.mp3', audioData); ``` ## Usage Examples ### Basic Chat ```javascript const { uncloseai } = require('./uncloseai_lib'); const client = new uncloseai(); const response = await client.chat({ model: 'auto', messages: [ { role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: 'What is JavaScript?' } ], maxTokens: 100 }); console.log(response.choices[0].message.content); ``` ### Streaming Chat ```javascript for await (const chunk of client.chatStream({ model: 'auto', messages: [{ role: 'user', content: 'Write a haiku about code' }], maxTokens: 100 })) { const content = chunk.choices?.[0]?.delta?.content || ''; if (content) { process.stdout.write(content); } } console.log(); // newline ``` ### Multi-Turn Conversation ```javascript const messages = [ { role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: 'What is AI?' } ]; // First response const response1 = await client.chat({ model: 'auto', messages }); const assistantMsg = response1.choices[0].message.content; messages.push({ role: 'assistant', content: assistantMsg }); // Follow-up question messages.push({ role: 'user', content: 'Can you explain more?' }); const response2 = await client.chat({ model: 'auto', messages }); ``` ### Text-to-Speech ```javascript const fs = require('fs'); const audioData = await client.tts({ text: 'Hello from uncloseai.!', voice: 'alloy', model: 'tts-1' }); fs.writeFileSync('output.mp3', audioData); ``` ### Using Specific Models ```javascript // List available models const models = await client.listModels(); for (const model of models) { console.log(`${model.id} - Max tokens: ${model.max_tokens}`); } // Use specific model const response = await client.chat({ model: models[0].id, messages: [{ role: 'user', content: 'Hello' }] }); ``` ### Error Handling ```javascript const { uncloseai, uncloseaiError, ModelNotFoundError } = require('./uncloseai_lib'); const client = new uncloseai(); try { const response = await client.chat({ model: 'non-existent-model', messages: [{ role: 'user', content: 'Hello' }] }); } catch (error) { if (error instanceof ModelNotFoundError) { console.log(`Model error: ${error.message}`); } else if (error instanceof uncloseaiError) { console.log(`API error: ${error.message}`); } else { throw error; } } ``` ## Running Examples ```bash # Set environment variables export MODEL_ENDPOINT_1="https://hermes.ai.unturf.com/v1" export MODEL_ENDPOINT_2="https://qwen.ai.unturf.com/v1" export TTS_ENDPOINT_1="https://speech.ai.unturf.com/v1" # Run example script node examples.js ``` ## Docker Usage ```bash # Build docker build -t uncloseai-nodejs . # Run examples docker run -e MODEL_ENDPOINT_1="https://..." uncloseai-nodejs node examples.js ``` ## Compatibility Tested with: - ✅ vLLM (v0.5.0+) - ✅ Ollama (v0.1.0+) - ✅ OpenAI API (compatible endpoints) ## Error Types - `uncloseaiError` - Base error class for all library errors - `ConnectionError` - Network connection errors - `ModelNotFoundError` - Requested model not available - `StreamingError` - Errors during streaming requests ## License MIT License - See LICENSE file for details ## Contributing Contributions welcome! Please submit pull requests or open issues. ## Support For issues, questions, or contributions, please visit: https://github.com/yourusername/uncloseai ## Changelog ### v1.0.0 (2025-10-13) - Initial release - Streaming and non-streaming chat support - Text-to-speech generation - Automatic model discovery - Zero external dependencies - Comprehensive error handling