@nullplatform/llm-gateway-sdk
Version:
SDK for LLM Gateway plugin development
151 lines • 5 kB
JavaScript
;
// packages/sdk/src/utils/helpers.ts
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateRequestId = generateRequestId;
exports.calculateTokenEstimate = calculateTokenEstimate;
exports.estimateRequestCost = estimateRequestCost;
exports.createContextFromRequest = createContextFromRequest;
exports.mergeConfigs = mergeConfigs;
exports.sleep = sleep;
exports.retry = retry;
exports.truncateString = truncateString;
exports.formatBytes = formatBytes;
exports.formatDuration = formatDuration;
exports.isValidUrl = isValidUrl;
exports.parseContentType = parseContentType;
exports.deepClone = deepClone;
function generateRequestId() {
return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
function calculateTokenEstimate(text) {
// Rough estimation: ~4 characters per token for English text
return Math.ceil(text.length / 4);
}
function estimateRequestCost(request, model) {
// Basic cost estimation - should be overridden by provider-specific implementations
const inputTokens = request.messages.reduce((total, msg) => total + calculateTokenEstimate(msg.content), 0);
// Default pricing (per 1K tokens)
const defaultPricing = {
input: 0.001, // $0.001 per 1K input tokens
output: 0.002 // $0.002 per 1K output tokens
};
const estimatedOutputTokens = request.max_tokens || Math.min(inputTokens * 2, 4000);
return (inputTokens / 1000) * defaultPricing.input +
(estimatedOutputTokens / 1000) * defaultPricing.output;
}
function createContextFromRequest(request, requestId, additionalData = {}) {
return {
request_id: requestId || generateRequestId(),
request,
plugin_data: new Map(),
metrics: {
start_time: Date.now()
},
headers: {},
query_params: {},
custom: {},
...additionalData
};
}
function mergeConfigs(base, override) {
const result = { ...base };
for (const [key, value] of Object.entries(override)) {
if (value !== undefined) {
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
result[key] = mergeConfigs(result[key] || {}, value);
}
else {
result[key] = value;
}
}
}
return result;
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function retry(fn, options) {
const { attempts, delay, backoff = 'fixed', shouldRetry = () => true } = options;
return new Promise(async (resolve, reject) => {
for (let attempt = 1; attempt <= attempts; attempt++) {
try {
const result = await fn();
resolve(result);
return;
}
catch (error) {
const err = error;
if (attempt === attempts || !shouldRetry(err)) {
reject(error);
return;
}
const waitTime = backoff === 'exponential'
? delay * Math.pow(2, attempt - 1)
: delay;
await sleep(waitTime);
}
}
});
}
function truncateString(str, maxLength) {
if (str.length <= maxLength)
return str;
return str.substring(0, maxLength - 3) + '...';
}
function formatBytes(bytes) {
if (bytes === 0)
return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
function formatDuration(ms) {
if (ms < 1000)
return `${ms}ms`;
if (ms < 60000)
return `${(ms / 1000).toFixed(1)}s`;
if (ms < 3600000)
return `${(ms / 60000).toFixed(1)}m`;
return `${(ms / 3600000).toFixed(1)}h`;
}
function isValidUrl(url) {
try {
new URL(url);
return true;
}
catch {
return false;
}
}
function parseContentType(contentType) {
const [type, ...params] = contentType.split(';').map(s => s.trim());
const charset = params
.find(p => p.startsWith('charset='))
?.split('=')[1];
return { type, charset };
}
function deepClone(obj) {
if (obj === null || typeof obj !== 'object')
return obj;
if (obj instanceof Date)
return new Date(obj.getTime());
if (obj instanceof Array)
return obj.map(item => deepClone(item));
if (obj instanceof Map) {
const cloned = new Map();
obj.forEach((value, key) => cloned.set(key, deepClone(value)));
return cloned;
}
if (obj instanceof Set) {
const cloned = new Set();
obj.forEach(value => cloned.add(deepClone(value)));
return cloned;
}
const cloned = {};
Object.keys(obj).forEach(key => {
cloned[key] = deepClone(obj[key]);
});
return cloned;
}
//# sourceMappingURL=helpers.js.map