UNPKG

@revenium/perplexity

Version:
131 lines 5.21 kB
"use strict"; /** * Revenium Metering Module * Handles tracking and sending metering data to Revenium */ Object.defineProperty(exports, "__esModule", { value: true }); exports.generateTransactionId = generateTransactionId; exports.buildMeteringData = buildMeteringData; exports.sendMeteringData = sendMeteringData; const revenium_config_1 = require("../config/revenium-config"); const logger_1 = require("../../utils/logger"); /** * Generate a unique transaction ID */ function generateTransactionId() { return `txn_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`; } /** * Format timestamp to ISO string */ function formatTimestamp(date) { return date.toISOString(); } /** * Calculate duration in milliseconds */ function calculateDuration(startTime, endTime) { return endTime.getTime() - startTime.getTime(); } /** * Build metering data from request information */ function buildMeteringData(params) { const { model, startTime, endTime, inputTokens, outputTokens, totalTokens, reasoningTokens = 0, cachedTokens = 0, transactionId, isStreamed, stopReason, usageMetadata = {}, } = params; const config = (0, revenium_config_1.getReveniumConfig)(); const agent = "perplexity"; const costType = "TOKEN"; const operationType = "CHAT"; // Build subscriber information const subscriberId = usageMetadata.subscriber?.id || usageMetadata.subscriberId || `user-${generateTransactionId()}`; const subscriberEmail = usageMetadata.subscriber?.email || usageMetadata.subscriberEmail || `user@${agent}.ai`; const subscriberCredential = usageMetadata.subscriber?.credential || (usageMetadata.subscriberCredentialName && usageMetadata.subscriberCredential ? { name: usageMetadata.subscriberCredentialName, value: usageMetadata.subscriberCredential, } : { name: "default", value: "default-credential", }); const subscriber = { id: subscriberId, email: subscriberEmail, credential: subscriberCredential, }; // Build the payload in the exact order expected by Revenium API v2 const payload = { stopReason: "END", costType: "AI", // Fixed value as per Google middleware isStreamed, taskType: "AI", // Fixed value as per Google middleware agent: usageMetadata.agent || agent, operationType: usageMetadata.operationType || operationType, inputTokenCount: usageMetadata.inputTokenCount ?? inputTokens, outputTokenCount: usageMetadata.outputTokenCount ?? outputTokens, reasoningTokenCount: usageMetadata.reasoningTokenCount ?? reasoningTokens, cacheCreationTokenCount: usageMetadata.cacheCreationTokenCount ?? cachedTokens, cacheReadTokenCount: usageMetadata.cacheReadTokenCount ?? 0, totalTokenCount: usageMetadata.totalTokenCount ?? totalTokens, organizationId: usageMetadata.organizationId || "my-customers-name", productId: usageMetadata.productId || "free-trial", subscriber, model, transactionId: usageMetadata.transactionId || transactionId, responseTime: usageMetadata.responseTime || formatTimestamp(endTime), requestDuration: calculateDuration(startTime, endTime), provider: agent, requestTime: usageMetadata.requestTime || formatTimestamp(startTime), completionStartTime: usageMetadata.completionStartTime || formatTimestamp(endTime), timeToFirstToken: usageMetadata.timeToFirstToken || 0, middleware_source: "node", }; // Only add traceId if it's provided if (usageMetadata.traceId) { payload.traceId = usageMetadata.traceId; } return payload; } /** * Send metering data to Revenium */ async function sendMeteringData(meteringData) { if (!(0, revenium_config_1.isReveniumEnabled)()) { logger_1.logger.debug("Revenium metering is disabled, skipping metering data"); return; } const config = (0, revenium_config_1.getReveniumConfig)(); if (!config) { logger_1.logger.warn("Revenium configuration not initialized"); return; } try { const url = `${config.meteringBaseUrl}/v2/ai/completions`; logger_1.logger.debug("Sending metering data to Revenium:", JSON.stringify(meteringData, null, 2)); const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", "x-api-key": config.meteringApiKey, accept: "application/json", }, body: JSON.stringify(meteringData), }); if (!response.ok) { const errorData = await response.text(); logger_1.logger.error(`Metering API request failed with status ${response.status}: ${errorData}`); return; } logger_1.logger.info("Metering data sent successfully to Revenium"); } catch (error) { logger_1.logger.error("Error sending metering data:", error.message); } } //# sourceMappingURL=metering.js.map