UNPKG

bettercx-widget

Version:

Professional AI-powered chat widget for BetterCX platform. Seamlessly integrate intelligent customer support into any website.

122 lines (121 loc) 4.11 kB
/** * API Service * Handles all API communication with backend services */ import { AuthService } from "./auth.service"; export class ApiService { authService; dbServiceUrl; aiServiceUrl; constructor(dbServiceUrl = 'http://localhost:8000', aiServiceUrl = 'http://localhost:8081', authService) { this.dbServiceUrl = dbServiceUrl; this.aiServiceUrl = aiServiceUrl; this.authService = authService || new AuthService(dbServiceUrl); } /** * Fetch widget configuration from backend */ async getWidgetConfig(organizationId) { const token = this.authService.getToken(); if (!token) { throw new Error('No valid session token available'); } try { const response = await fetch(`${this.dbServiceUrl}/api/widgets/org/${organizationId}/widget-config/`, { method: 'GET', headers: { 'Content-Type': 'application/json', ...this.authService.getAuthHeader(), }, }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`); } return await response.json(); } catch (error) { throw error; } } /** * Send a chat message to the AI service */ async sendMessage(message) { const token = this.authService.getToken(); if (!token) { throw new Error('No valid session token available'); } const request = { content: message, }; try { const response = await fetch(`${this.aiServiceUrl}/widget/ai/respond/`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...this.authService.getAuthHeader(), }, body: JSON.stringify(request), }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`); } // Return the response stream for streaming return response.body; } catch (error) { throw error; } } /** * Parse streaming response from AI service */ async *parseStreamResponse(stream) { const reader = stream.getReader(); const decoder = new TextDecoder(); let currentEventType = 'streaming_output'; // Default event type try { while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value, { stream: true }); const lines = chunk.split('\n'); for (const line of lines) { if (line.startsWith('event: ')) { currentEventType = line.slice(7).trim(); continue; } if (line.startsWith('data: ')) { const data = line.slice(6); if (data === '[DONE]') { return; } try { const parsed = JSON.parse(data); if (parsed.content) { yield { type: currentEventType, content: parsed.content }; } } catch (e) { // Skip invalid JSON continue; } } } } } finally { reader.releaseLock(); } } /** * Get the auth service instance */ getAuthService() { return this.authService; } } //# sourceMappingURL=api.service.js.map