UNPKG

vly-integrations

Version:

First-order integrations for AI, email, and payments with automatic usage billing

535 lines (528 loc) 14.7 kB
'use strict'; var openaiCompatible = require('@ai-sdk/openai-compatible'); var ai = require('ai'); // src/ai/index.ts var VlyAI = class { provider; config; constructor(config) { this.config = config; this.provider = openaiCompatible.createOpenAICompatible({ name: "vly-gateway", baseURL: "https://ai-gateway.vly.ai/v1/llm", headers: { "Authorization": `Bearer ${config.deploymentToken}` } }); } getModel(modelName) { return this.provider(modelName || "gpt-5"); } mapMessages(messages) { return messages.map((msg) => ({ role: msg.role, content: msg.content })); } async completion(request, _options) { if (this.config.debug) { console.log("[Vly] Creating AI completion", { model: request.model }); } try { const model = this.getModel(request.model); const messages = this.mapMessages(request.messages); const result = await ai.generateText({ model, messages, temperature: request.temperature, maxOutputTokens: request.maxTokens }); const responseData = { id: `vly-${Date.now()}`, choices: [{ message: { role: "assistant", content: result.text }, finishReason: result.finishReason || "stop" }], usage: { promptTokens: result.usage?.inputTokens || 0, completionTokens: result.usage?.outputTokens || 0, totalTokens: result.usage?.totalTokens || 0 } }; if (this.config.debug) { console.log("[Vly] AI completion successful", { tokensUsed: responseData.usage.totalTokens }); } return { success: true, data: responseData }; } catch (error) { if (this.config.debug) { console.error("[Vly] AI completion failed", { error: error.message }); } return { success: false, error: error.message || "Request failed" }; } } async streamCompletion(request, onChunk, _options) { if (this.config.debug) { console.log("[Vly] Creating streaming AI completion", { model: request.model }); } try { const model = this.getModel(request.model); const messages = this.mapMessages(request.messages); const result = await ai.streamText({ model, messages, temperature: request.temperature, maxOutputTokens: request.maxTokens }); let fullResponse = ""; for await (const delta of result.textStream) { fullResponse += delta; onChunk(delta); } const usage = await result.usage; const responseData = { id: `vly-stream-${Date.now()}`, choices: [{ message: { role: "assistant", content: fullResponse }, finishReason: "stop" }], usage: { promptTokens: usage?.inputTokens || 0, completionTokens: usage?.outputTokens || 0, totalTokens: usage?.totalTokens || 0 } }; if (this.config.debug) { console.log("[Vly] Streaming AI completion successful", { tokensUsed: responseData.usage.totalTokens }); } return { success: true, data: responseData }; } catch (error) { if (this.config.debug) { console.error("[Vly] Streaming AI completion failed", { error: error.message }); } return { success: false, error: error.message || "Streaming request failed" }; } } async embeddings(input, _options) { if (this.config.debug) { console.log("[Vly] Creating embeddings", { inputCount: Array.isArray(input) ? input.length : 1 }); } return { success: false, error: "Embeddings not yet supported with AI SDK OpenAI-compatible provider" }; } // Helper method to get the provider for direct AI SDK usage getProvider() { return this.provider; } }; // src/client.ts var VlyClient = class { config; constructor(config) { this.config = { deploymentToken: config.deploymentToken, debug: config.debug || false }; } async request(endpoint, method, data, options) { const url = `https://ai-gateway.vly.ai${endpoint}`; const headers = { "Authorization": `Bearer ${this.config.deploymentToken}`, "Content-Type": "application/json", "X-Vly-Version": "0.1.0" }; const fetchOptions = { method, headers, body: data ? JSON.stringify(data) : void 0 }; const controller = new AbortController(); const timeout = options?.timeout || 3e4; const timeoutId = setTimeout(() => controller.abort(), timeout); fetchOptions.signal = controller.signal; try { const response = await fetch(url, fetchOptions); clearTimeout(timeoutId); const responseData = await response.json().catch(() => ({})); if (response.ok) { return { success: true, data: responseData, usage: responseData?.usage }; } else { const error = responseData?.error || `Request failed with status ${response.status}`; if (this.config.debug) { console.error(`Vly API Error: ${error}`, { endpoint, status: response.status, data: responseData }); } return { success: false, error }; } } catch (error) { clearTimeout(timeoutId); const errorMessage = error.name === "AbortError" ? "Request timeout" : error.message || "Unknown error occurred"; if (this.config.debug) { console.error(`Vly API Request Failed: ${errorMessage}`, { endpoint, error }); } if (options?.retries && options.retries > 0) { if (this.config.debug) { console.log(`Retrying request... (${options.retries} retries left)`); } await new Promise((resolve) => setTimeout(resolve, 1e3)); return this.request(endpoint, method, data, { ...options, retries: options.retries - 1 }); } return { success: false, error: errorMessage }; } } log(message, data) { if (this.config.debug) { console.log(`[Vly] ${message}`, data || ""); } } }; // src/email/index.ts var VlyEmail = class extends VlyClient { async send(email, options) { this.log("Sending email", { to: email.to, subject: email.subject }); const payload = { to: Array.isArray(email.to) ? email.to : [email.to], from: email.from || "noreply@vly.io", subject: email.subject, html: email.html, text: email.text, attachments: email.attachments, replyTo: email.replyTo, cc: email.cc ? Array.isArray(email.cc) ? email.cc : [email.cc] : void 0, bcc: email.bcc ? Array.isArray(email.bcc) ? email.bcc : [email.bcc] : void 0 }; const response = await this.request( "/v1/email/send", "POST", payload, options ); if (response.success) { this.log("Email sent successfully", { id: response.data?.id, status: response.data?.status }); } return response; } async sendBatch(emails, options) { this.log("Sending batch emails", { count: emails.length }); const payload = { emails: emails.map((email) => ({ to: Array.isArray(email.to) ? email.to : [email.to], from: email.from || "noreply@vly.io", subject: email.subject, html: email.html, text: email.text, attachments: email.attachments, replyTo: email.replyTo, cc: email.cc ? Array.isArray(email.cc) ? email.cc : [email.cc] : void 0, bcc: email.bcc ? Array.isArray(email.bcc) ? email.bcc : [email.bcc] : void 0 })) }; return this.request( "/v1/email/batch", "POST", payload, options ); } async getStatus(emailId, options) { this.log("Getting email status", { emailId }); return this.request( `/v1/email/status/${emailId}`, "GET", void 0, options ); } async verifyDomain(domain, options) { this.log("Verifying domain", { domain }); return this.request( "/v1/email/domains/verify", "POST", { domain }, options ); } async listDomains(options) { this.log("Listing email domains"); return this.request( "/v1/email/domains", "GET", void 0, options ); } }; // src/payments/index.ts var VlyPayments = class extends VlyClient { async createPaymentIntent(intent, options) { this.log("Creating payment intent", { amount: intent.amount, currency: intent.currency }); const payload = { amount: intent.amount, currency: intent.currency || "usd", description: intent.description, metadata: intent.metadata, customer: intent.customer }; const response = await this.request( "/payments/intents", "POST", payload, options ); if (response.success) { this.log("Payment intent created", { id: response.data?.id, status: response.data?.status }); } return response; } async confirmPaymentIntent(intentId, paymentMethodId, options) { this.log("Confirming payment intent", { intentId }); return this.request( `/payments/intents/${intentId}/confirm`, "POST", { paymentMethodId }, options ); } async getPaymentIntent(intentId, options) { this.log("Getting payment intent", { intentId }); return this.request( `/payments/intents/${intentId}`, "GET", void 0, options ); } async cancelPaymentIntent(intentId, options) { this.log("Canceling payment intent", { intentId }); return this.request( `/payments/intents/${intentId}/cancel`, "POST", void 0, options ); } async createSubscription(subscription, options) { this.log("Creating subscription", { customerId: subscription.customerId, priceId: subscription.priceId }); const response = await this.request( "/payments/subscriptions", "POST", subscription, options ); if (response.success) { this.log("Subscription created", { id: response.data?.id, status: response.data?.status }); } return response; } async updateSubscription(subscriptionId, updates, options) { this.log("Updating subscription", { subscriptionId }); return this.request( `/payments/subscriptions/${subscriptionId}`, "PUT", updates, options ); } async cancelSubscription(subscriptionId, immediately, options) { this.log("Canceling subscription", { subscriptionId, immediately }); return this.request( `/payments/subscriptions/${subscriptionId}/cancel`, "POST", { immediately }, options ); } async getSubscription(subscriptionId, options) { this.log("Getting subscription", { subscriptionId }); return this.request( `/payments/subscriptions/${subscriptionId}`, "GET", void 0, options ); } async listSubscriptions(customerId, options) { this.log("Listing subscriptions", { customerId }); const params = new URLSearchParams(); if (customerId) params.append("customerId", customerId); if (options?.limit) params.append("limit", options.limit.toString()); if (options?.offset) params.append("offset", options.offset.toString()); const queryString = params.toString(); const endpoint = `/payments/subscriptions${queryString ? `?${queryString}` : ""}`; return this.request(endpoint, "GET", void 0, options); } async createCustomerPortal(session, options) { this.log("Creating customer portal session", { customerId: session.customerId }); const response = await this.request( "/payments/portal", "POST", session, options ); if (response.success) { this.log("Customer portal session created", { id: response.data?.id, url: response.data?.url }); } return response; } async createCheckoutSession(session, options) { this.log("Creating checkout session", { mode: session.mode, lineItems: session.lineItems.length }); return this.request( "/payments/checkout", "POST", session, options ); } async createCustomer(customer, options) { this.log("Creating customer", { email: customer.email }); return this.request( "/payments/customers", "POST", customer, options ); } async getCustomer(customerId, options) { this.log("Getting customer", { customerId }); return this.request( `/payments/customers/${customerId}`, "GET", void 0, options ); } async updateCustomer(customerId, updates, options) { this.log("Updating customer", { customerId }); return this.request( `/payments/customers/${customerId}`, "PUT", updates, options ); } async listPaymentMethods(customerId, options) { this.log("Listing payment methods", { customerId }); return this.request( `/payments/customers/${customerId}/payment-methods`, "GET", void 0, options ); } async attachPaymentMethod(paymentMethodId, customerId, options) { this.log("Attaching payment method", { paymentMethodId, customerId }); return this.request( `/payments/payment-methods/${paymentMethodId}/attach`, "POST", { customerId }, options ); } async detachPaymentMethod(paymentMethodId, options) { this.log("Detaching payment method", { paymentMethodId }); return this.request( `/payments/payment-methods/${paymentMethodId}/detach`, "POST", void 0, options ); } }; // src/index.ts var VlyIntegrations = class { ai; email; payments; constructor(config) { if (!config.deploymentToken) { throw new Error("Deployment token is required"); } this.ai = new VlyAI(config); this.email = new VlyEmail(config); this.payments = new VlyPayments(config); } }; function createVlyIntegrations(config) { return new VlyIntegrations(config); } exports.VlyAI = VlyAI; exports.VlyEmail = VlyEmail; exports.VlyIntegrations = VlyIntegrations; exports.VlyPayments = VlyPayments; exports.createVlyIntegrations = createVlyIntegrations; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map