Spaces:
Running
Running
| import type { | |
| ChatMessage, | |
| ChatResponse, | |
| ImageResponse, | |
| ModelsResponse, | |
| StatsResponse, | |
| HealthResponse, | |
| AuthConfig, | |
| AuthResponse, | |
| AuthUser, | |
| } from './types' | |
| const BASE_URL = '/api' | |
| // --------------------------------------------------------------------------- | |
| // Token management | |
| // --------------------------------------------------------------------------- | |
| const TOKEN_KEY = 'lp_auth_token' | |
| export function getToken(): string | null { | |
| return localStorage.getItem(TOKEN_KEY) | |
| } | |
| export function setToken(token: string) { | |
| localStorage.setItem(TOKEN_KEY, token) | |
| } | |
| export function clearToken() { | |
| localStorage.removeItem(TOKEN_KEY) | |
| } | |
| function authHeaders(): Record<string, string> { | |
| const token = getToken() | |
| return token ? { Authorization: `Bearer ${token}` } : {} | |
| } | |
| // --------------------------------------------------------------------------- | |
| // Generic request helper | |
| // --------------------------------------------------------------------------- | |
| async function request<T>(path: string, options?: RequestInit): Promise<T> { | |
| const res = await fetch(`${BASE_URL}${path}`, { | |
| headers: { 'Content-Type': 'application/json', ...authHeaders() }, | |
| ...options, | |
| }) | |
| if (!res.ok) { | |
| const err = await res.json().catch(() => ({ detail: res.statusText })) | |
| throw new Error(err.detail || `HTTP ${res.status}`) | |
| } | |
| return res.json() | |
| } | |
| // --------------------------------------------------------------------------- | |
| // Auth | |
| // --------------------------------------------------------------------------- | |
| export async function getAuthConfig(): Promise<AuthConfig> { | |
| return request('/auth/config') | |
| } | |
| export async function loginWithGoogle(credential: string): Promise<AuthResponse> { | |
| return request('/auth/google', { | |
| method: 'POST', | |
| body: JSON.stringify({ credential }), | |
| }) | |
| } | |
| export async function getMe(): Promise<AuthUser> { | |
| return request('/auth/me') | |
| } | |
| // --------------------------------------------------------------------------- | |
| // Public API | |
| // --------------------------------------------------------------------------- | |
| export async function getHealth(): Promise<HealthResponse> { | |
| return request('/health') | |
| } | |
| export async function getModels(): Promise<ModelsResponse> { | |
| return request('/models') | |
| } | |
| export async function getStats(): Promise<StatsResponse> { | |
| return request('/stats') | |
| } | |
| // --------------------------------------------------------------------------- | |
| // Protected API | |
| // --------------------------------------------------------------------------- | |
| export async function sendChat( | |
| message: string, | |
| model: string, | |
| history: ChatMessage[], | |
| lang: string = 'hr', | |
| ): Promise<ChatResponse> { | |
| return request('/chat', { | |
| method: 'POST', | |
| body: JSON.stringify({ | |
| message, | |
| model, | |
| lang, | |
| history: history.map((m) => ({ role: m.role, content: m.content })), | |
| }), | |
| }) | |
| } | |
| export async function analyzeImage( | |
| imageFile: File, | |
| question: string, | |
| model: string, | |
| ): Promise<ImageResponse> { | |
| const formData = new FormData() | |
| formData.append('image', imageFile) | |
| formData.append('question', question) | |
| formData.append('model', model) | |
| const res = await fetch(`${BASE_URL}/analyze-image`, { | |
| method: 'POST', | |
| body: formData, | |
| headers: authHeaders(), | |
| }) | |
| if (!res.ok) { | |
| const err = await res.json().catch(() => ({ detail: res.statusText })) | |
| throw new Error(err.detail || `HTTP ${res.status}`) | |
| } | |
| return res.json() | |
| } | |