247 lines
6.8 KiB
JavaScript
247 lines
6.8 KiB
JavaScript
/**
|
||
* Brief Bench API Client
|
||
* Взаимодействие с FastAPI backend
|
||
*/
|
||
class BriefBenchAPI {
|
||
constructor() {
|
||
this.baseURL = '/api/v1'
|
||
}
|
||
|
||
// ============================================
|
||
// Internal Helpers
|
||
// ============================================
|
||
|
||
_getToken() {
|
||
return localStorage.getItem('access_token')
|
||
}
|
||
|
||
_setToken(token) {
|
||
localStorage.setItem('access_token', token)
|
||
}
|
||
|
||
_clearToken() {
|
||
localStorage.removeItem('access_token')
|
||
}
|
||
|
||
_getHeaders(includeAuth = true) {
|
||
const headers = {
|
||
'Content-Type': 'application/json'
|
||
}
|
||
|
||
if (includeAuth) {
|
||
const token = this._getToken()
|
||
if (token) {
|
||
headers['Authorization'] = `Bearer ${token}`
|
||
}
|
||
}
|
||
|
||
return headers
|
||
}
|
||
|
||
async _handleResponse(response) {
|
||
// Handle 401 Unauthorized
|
||
if (response.status === 401) {
|
||
this._clearToken()
|
||
throw new Error('Сессия истекла. Пожалуйста, войдите снова.')
|
||
}
|
||
|
||
// Handle 502 Bad Gateway (RAG backend error)
|
||
if (response.status === 502) {
|
||
throw new Error('RAG backend недоступен или вернул ошибку')
|
||
}
|
||
|
||
// Handle other errors
|
||
if (!response.ok) {
|
||
const errorData = await response.json().catch(() => ({}))
|
||
throw new Error(errorData.detail || `HTTP ${response.status}: ${response.statusText}`)
|
||
}
|
||
|
||
// Handle 204 No Content
|
||
if (response.status === 204) {
|
||
return null
|
||
}
|
||
|
||
return await response.json()
|
||
}
|
||
|
||
async _request(endpoint, options = {}) {
|
||
const url = `${this.baseURL}${endpoint}`
|
||
|
||
try {
|
||
const response = await fetch(url, options)
|
||
return await this._handleResponse(response)
|
||
} catch (error) {
|
||
console.error(`API request failed: ${endpoint}`, error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
// ============================================
|
||
// Auth API
|
||
// ============================================
|
||
|
||
/**
|
||
* Авторизация с 8-значным логином
|
||
* @param {string} login - 8-значный логин
|
||
* @returns {Promise<{access_token: string, user: object}>}
|
||
*/
|
||
async login(login) {
|
||
const response = await this._request(`/auth/login?login=${login}`, {
|
||
method: 'POST',
|
||
headers: this._getHeaders(false)
|
||
})
|
||
|
||
// Сохранить токен
|
||
this._setToken(response.access_token)
|
||
|
||
return response
|
||
}
|
||
|
||
/**
|
||
* Выход (очистка токена)
|
||
*/
|
||
logout() {
|
||
this._clearToken()
|
||
window.location.reload()
|
||
}
|
||
|
||
/**
|
||
* Проверка авторизации
|
||
* @returns {boolean}
|
||
*/
|
||
isAuthenticated() {
|
||
return !!this._getToken()
|
||
}
|
||
|
||
// ============================================
|
||
// Settings API
|
||
// ============================================
|
||
|
||
/**
|
||
* Получить настройки пользователя для всех окружений
|
||
* @returns {Promise<{user_id: string, settings: object, updated_at: string}>}
|
||
*/
|
||
async getSettings() {
|
||
return await this._request('/settings', {
|
||
method: 'GET',
|
||
headers: this._getHeaders()
|
||
})
|
||
}
|
||
|
||
/**
|
||
* Обновить настройки пользователя
|
||
* @param {object} settings - Объект с настройками для окружений
|
||
* @returns {Promise<{user_id: string, settings: object, updated_at: string}>}
|
||
*/
|
||
async updateSettings(settings) {
|
||
return await this._request('/settings', {
|
||
method: 'PATCH',
|
||
headers: this._getHeaders(),
|
||
body: JSON.stringify({ settings })
|
||
})
|
||
}
|
||
|
||
// ============================================
|
||
// Query API
|
||
// ============================================
|
||
|
||
/**
|
||
* Отправить batch запрос (Bench mode)
|
||
* @param {string} environment - Окружение (ift/psi/prod)
|
||
* @param {Array<{body: string, with_docs: boolean}>} questions - Массив вопросов
|
||
* @returns {Promise<{request_id: string, timestamp: string, environment: string, response: object}>}
|
||
*/
|
||
async benchQuery(environment, questions) {
|
||
return await this._request('/query/bench', {
|
||
method: 'POST',
|
||
headers: this._getHeaders(),
|
||
body: JSON.stringify({
|
||
environment,
|
||
questions
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* Отправить последовательные запросы (Backend mode)
|
||
* @param {string} environment - Окружение (ift/psi/prod)
|
||
* @param {Array<{body: string, with_docs: boolean}>} questions - Массив вопросов
|
||
* @param {boolean} resetSession - Сбрасывать ли сессию после каждого вопроса
|
||
* @returns {Promise<{request_id: string, timestamp: string, environment: string, response: object}>}
|
||
*/
|
||
async backendQuery(environment, questions, resetSession = true) {
|
||
return await this._request('/query/backend', {
|
||
method: 'POST',
|
||
headers: this._getHeaders(),
|
||
body: JSON.stringify({
|
||
environment,
|
||
questions,
|
||
reset_session: resetSession
|
||
})
|
||
})
|
||
}
|
||
|
||
// ============================================
|
||
// Analysis Sessions API
|
||
// ============================================
|
||
|
||
/**
|
||
* Сохранить сессию анализа
|
||
* @param {object} sessionData - Данные сессии
|
||
* @returns {Promise<object>}
|
||
*/
|
||
async saveSession(sessionData) {
|
||
return await this._request('/analysis/sessions', {
|
||
method: 'POST',
|
||
headers: this._getHeaders(),
|
||
body: JSON.stringify(sessionData)
|
||
})
|
||
}
|
||
|
||
/**
|
||
* Получить список сессий
|
||
* @param {string|null} environment - Фильтр по окружению (опционально)
|
||
* @param {number} limit - Лимит результатов
|
||
* @param {number} offset - Смещение для пагинации
|
||
* @returns {Promise<{sessions: Array, total: number}>}
|
||
*/
|
||
async getSessions(environment = null, limit = 50, offset = 0) {
|
||
const params = new URLSearchParams({ limit, offset })
|
||
if (environment) {
|
||
params.append('environment', environment)
|
||
}
|
||
|
||
return await this._request(`/analysis/sessions?${params}`, {
|
||
method: 'GET',
|
||
headers: this._getHeaders()
|
||
})
|
||
}
|
||
|
||
/**
|
||
* Получить конкретную сессию
|
||
* @param {string} sessionId - ID сессии
|
||
* @returns {Promise<object>}
|
||
*/
|
||
async getSession(sessionId) {
|
||
return await this._request(`/analysis/sessions/${sessionId}`, {
|
||
method: 'GET',
|
||
headers: this._getHeaders()
|
||
})
|
||
}
|
||
|
||
/**
|
||
* Удалить сессию
|
||
* @param {string} sessionId - ID сессии
|
||
* @returns {Promise<null>}
|
||
*/
|
||
async deleteSession(sessionId) {
|
||
return await this._request(`/analysis/sessions/${sessionId}`, {
|
||
method: 'DELETE',
|
||
headers: this._getHeaders()
|
||
})
|
||
}
|
||
}
|
||
|
||
// Export API client instance
|
||
const api = new BriefBenchAPI()
|