UNPKG

hashub-vector

Version:

Official TypeScript/JavaScript SDK for Hashub Vector API - High-quality multilingual text embeddings with Turkish excellence

390 lines (384 loc) 12 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var axios = require('axios'); /** * Base error class for Hashub Vector SDK */ class HashubVectorError extends Error { constructor(message, code, status, details) { super(message); this.name = 'HashubVectorError'; this.code = code; this.status = status; this.details = details; // Maintain proper stack trace for where our error was thrown if (Error.captureStackTrace) { Error.captureStackTrace(this, HashubVectorError); } } } /** * Authentication error (401) */ class AuthenticationError extends HashubVectorError { constructor(message = 'Invalid API key or authentication failed') { super(message, 'AUTHENTICATION_ERROR', 401); this.name = 'AuthenticationError'; } } /** * Rate limit error (429) */ class RateLimitError extends HashubVectorError { constructor(message = 'Rate limit exceeded', retryAfter) { super(message, 'RATE_LIMIT_ERROR', 429); this.name = 'RateLimitError'; this.retryAfter = retryAfter; } } /** * Quota exceeded error (402) */ class QuotaExceededError extends HashubVectorError { constructor(message = 'Token quota exceeded') { super(message, 'QUOTA_EXCEEDED_ERROR', 402); this.name = 'QuotaExceededError'; } } /** * Validation error (400) */ class ValidationError extends HashubVectorError { constructor(message = 'Request validation failed') { super(message, 'VALIDATION_ERROR', 400); this.name = 'ValidationError'; } } /** * Server error (500) */ class ServerError extends HashubVectorError { constructor(message = 'Internal server error') { super(message, 'SERVER_ERROR', 500); this.name = 'ServerError'; } } /** * Network error (connection issues) */ class NetworkError extends HashubVectorError { constructor(message = 'Network connection error') { super(message, 'NETWORK_ERROR'); this.name = 'NetworkError'; } } /** * Timeout error */ class TimeoutError extends HashubVectorError { constructor(message = 'Request timeout') { super(message, 'TIMEOUT_ERROR'); this.name = 'TimeoutError'; } } /** * Hashub Vector SDK Client for TypeScript/JavaScript * * Provides high-quality multilingual text embeddings with exceptional Turkish language support. * * @example * ```typescript * import { HashubVector } from 'hashub-vector'; * * const client = new HashubVector({ * apiKey: 'your-api-key' * }); * * // Single embedding * const response = await client.vectorize({ * text: 'Merhaba dünya!', * model: 'gte_base' * }); * * console.log(response.vector); // [0.1, -0.2, ...] * ``` */ class HashubVector { /** * Create a new Hashub Vector client * * @param config - Configuration options */ constructor(config) { this.config = { baseUrl: 'https://api.vector.hashub.dev', timeout: 30000, maxRetries: 3, headers: {}, ...config, }; this.client = axios.create({ baseURL: this.config.baseUrl, timeout: this.config.timeout, headers: { Authorization: `Bearer ${this.config.apiKey}`, 'Content-Type': 'application/json', 'User-Agent': 'hashub-vector-js/1.0.0', ...this.config.headers, }, }); // Add response interceptor for error handling this.client.interceptors.response.use((response) => response, (error) => this.handleError(error)); } /** * Generate embedding for a single text * * @param request - Vectorization request * @returns Promise<VectorizeResponse> * * @example * ```typescript * const response = await client.vectorize({ * text: 'Artificial intelligence is transforming the world', * model: 'gte_base' * }); * * console.log(`Vector dimension: ${response.dimension}`); * console.log(`Tokens used: ${response.tokens}`); * ``` */ async vectorize(request) { const response = await this.makeRequest('POST', '/vectorize', { text: request.text, model: request.model || 'e5_base', chunk_size: request.chunkSize, chunk_overlap: request.chunkOverlap, }); return response; } /** * Generate embeddings for multiple texts (batch processing) * * @param request - Batch vectorization request * @returns Promise<VectorizeBatchResponse> * * @example * ```typescript * const response = await client.vectorizeBatch({ * texts: [ * 'Hello world', * 'Merhaba dünya', * 'Bonjour monde' * ], * model: 'gte_base' * }); * * console.log(`Processed ${response.count} texts`); * console.log(`Total tokens: ${response.totalTokens}`); * ``` */ async vectorizeBatch(request) { const response = await this.makeRequest('POST', '/vectorize-batch', { texts: request.texts, model: request.model || 'e5_base', chunk_size: request.chunkSize, chunk_overlap: request.chunkOverlap, }); return response; } /** * Calculate cosine similarity between two texts * * @param request - Similarity calculation request * @returns Promise<SimilarityResponse> * * @example * ```typescript * const response = await client.similarity({ * text1: 'Machine learning', * text2: 'Makine öğrenmesi', * model: 'gte_base' * }); * * console.log(`Similarity: ${response.similarity.toFixed(3)}`); * ``` */ async similarity(request) { const response = await this.makeRequest('POST', '/similarity', { text1: request.text1, text2: request.text2, model: request.model || 'e5_base', }); return response; } /** * Get information about available models * * @returns Promise<ModelInfo[]> * * @example * ```typescript * const models = await client.getModels(); * * for (const model of models) { * console.log(`${model.alias}: ${model.description}`); * console.log(` Dimension: ${model.dimension}`); * console.log(` Max tokens: ${model.maxTokens}`); * console.log(` Turkish support: ${model.turkishSupport}/5`); * } * ``` */ async getModels() { const response = await this.makeRequest('GET', '/models'); return response.models; } /** * Get current usage statistics * * @returns Promise<UsageStats> * * @example * ```typescript * const usage = await client.getUsage(); * * console.log(`Tokens used: ${usage.tokensUsed.toLocaleString()}`); * console.log(`Usage: ${usage.tokensPercentageUsed.toFixed(1)}%`); * console.log(`Remaining: ${usage.tokensRemaining.toLocaleString()}`); * ``` */ async getUsage() { const response = await this.makeRequest('GET', '/usage'); return response; } /** * Get detailed usage statistics with daily breakdown * * @param from - Start date (YYYY-MM-DD format, optional) * @param to - End date (YYYY-MM-DD format, optional) * @returns Promise<UsageResponse> * * @example * ```typescript * // Get last 7 days usage * const usage = await client.getDetailedUsage('2025-08-01', '2025-08-07'); * * console.log(`Period: ${usage.period.from} to ${usage.period.to}`); * console.log(`Total tokens: ${usage.usage.tokensUsed}`); * * for (const day of usage.dailyUsage) { * console.log(`${day.date}: ${day.tokensUsed} tokens, ${day.requestCount} requests`); * } * ``` */ async getDetailedUsage(from, to) { const params = {}; if (from) params.from = from; if (to) params.to = to; const response = await this.makeRequest('GET', '/usage', undefined, { params }); return response; } /** * OpenAI-compatible embedding endpoint * * @param request - OpenAI-style embedding request * @returns Promise<OpenAIEmbeddingResponse> * * @example * ```typescript * // Drop-in replacement for OpenAI * const response = await client.createEmbedding({ * input: 'Your text here', * model: 'e5_base' * }); * * const embedding = response.data[0].embedding; * console.log(`Generated ${embedding.length}D embedding`); * ``` */ async createEmbedding(request) { const response = await this.makeRequest('POST', '/embeddings', { input: request.input, model: request.model, user: request.user, }); return response; } /** * Make HTTP request with error handling and retries */ async makeRequest(method, endpoint, data, config) { let lastError; for (let attempt = 0; attempt < this.config.maxRetries; attempt++) { try { const response = await this.client.request({ method, url: endpoint, data, ...config, }); return response.data; } catch (error) { lastError = error; // Don't retry on client errors (4xx except 429) or auth errors if (error.status && error.status >= 400 && error.status < 500 && error.status !== 429) { throw error; } // Wait before retry (exponential backoff) if (attempt < this.config.maxRetries - 1) { const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s... await new Promise(resolve => setTimeout(resolve, delay)); } } } throw lastError; } /** * Handle axios errors and convert to appropriate SDK errors */ handleError(error) { if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT') { throw new TimeoutError('Request timeout'); } if (error.code === 'ENOTFOUND' || error.code === 'ECONNREFUSED') { throw new NetworkError('Network connection error'); } if (!error.response) { throw new NetworkError(error.message || 'Network error'); } const { status, data } = error.response; const message = data?.message || data?.error || 'Unknown error'; switch (status) { case 401: throw new AuthenticationError(message); case 402: throw new QuotaExceededError(message); case 400: throw new ValidationError(message); case 429: { const retryAfter = error.response.headers['retry-after']; throw new RateLimitError(message, retryAfter ? parseInt(retryAfter) : undefined); } case 500: case 502: case 503: case 504: throw new ServerError(message); default: throw new HashubVectorError(message, 'API_ERROR', status, data); } } } exports.AuthenticationError = AuthenticationError; exports.HashubVector = HashubVector; exports.HashubVectorError = HashubVectorError; exports.NetworkError = NetworkError; exports.QuotaExceededError = QuotaExceededError; exports.RateLimitError = RateLimitError; exports.ServerError = ServerError; exports.TimeoutError = TimeoutError; exports.ValidationError = ValidationError; exports.default = HashubVector; //# sourceMappingURL=index.js.map