ZARAI / frontend /src /services /api.js
Srajal2579
Deploy JARVIS
3e646d9
Raw
History Blame Contribute Delete
6.95 kB
/**
* JARVIS API Service
* Centralized axios-based API calls to the FastAPI backend.
*/
import axios from 'axios'
// Base URL β€” uses Vite proxy in dev, env var in production
const BASE_URL = import.meta.env.VITE_API_URL || '/api'
const api = axios.create({
baseURL: BASE_URL,
timeout: 120_000, // 2 min β€” model inference can be slow
})
// ── Request interceptor ────────────────────────────
api.interceptors.request.use(
(config) => {
// Could add auth headers here in future
return config
},
(error) => Promise.reject(error),
)
// ── Response interceptor ───────────────────────────
api.interceptors.response.use(
(res) => res,
(error) => {
const message =
error.response?.data?.detail ||
error.response?.data?.message ||
error.message ||
'Unknown error'
return Promise.reject(new Error(message))
},
)
// ───────────────────────────────────────────────────
// CHAT
// ───────────────────────────────────────────────────
export const chatAPI = {
/**
* Send a chat message and receive AI response.
* @param {string} message
* @param {string|null} sessionId
* @param {string|null} imageCaption
*/
sendMessage: async (message, sessionId = null, imageCaption = null) => {
const res = await api.post('/chat/message', {
message,
session_id: sessionId,
image_caption: imageCaption,
})
return res.data
},
/**
* Get conversation history for a session.
*/
getHistory: async (sessionId, limit = 50) => {
const res = await api.get(`/chat/history/${sessionId}`, {
params: { limit },
})
return res.data
},
}
// ───────────────────────────────────────────────────
// IMAGE
// ───────────────────────────────────────────────────
export const imageAPI = {
/**
* Upload image file for analysis + optional question.
* @param {File} file
* @param {string|null} question
* @param {string|null} sessionId
*/
analyzeImage: async (file, question = null, sessionId = null) => {
const formData = new FormData()
formData.append('file', file)
if (question) formData.append('question', question)
if (sessionId) formData.append('session_id', sessionId)
const res = await api.post('/image/analyze', formData, {
headers: { 'Content-Type': 'multipart/form-data' },
timeout: 180_000, // vision models can be slow
})
return res.data
},
/**
* Quick caption only β€” no LLM.
*/
quickCaption: async (file) => {
const formData = new FormData()
formData.append('file', file)
const res = await api.post('/image/caption', formData, {
headers: { 'Content-Type': 'multipart/form-data' },
})
return res.data
},
}
// ───────────────────────────────────────────────────
// VOICE
// ───────────────────────────────────────────────────
export const voiceAPI = {
/**
* Transcribe audio Blob β†’ text.
* @param {Blob} audioBlob
* @param {string} language optional ISO language code
*/
transcribe: async (audioBlob, language = null) => {
const formData = new FormData()
formData.append('file', audioBlob, 'recording.webm')
if (language) formData.append('language', language)
const res = await api.post('/voice/transcribe', formData, {
headers: { 'Content-Type': 'multipart/form-data' },
timeout: 60_000,
})
return res.data
},
/**
* Full voice round-trip: audio β†’ text β†’ AI β†’ audio.
* @param {Blob} audioBlob
* @param {string|null} sessionId
* @param {boolean} ttsEnabled
*/
voiceInteract: async (audioBlob, sessionId = null, ttsEnabled = true) => {
const formData = new FormData()
formData.append('file', audioBlob, 'recording.webm')
if (sessionId) formData.append('session_id', sessionId)
formData.append('tts_enabled', ttsEnabled.toString())
const res = await api.post('/voice/interact', formData, {
headers: { 'Content-Type': 'multipart/form-data' },
timeout: 180_000,
})
return res.data
},
/**
* Text-to-speech: returns audio blob.
* @param {string} text
*/
speak: async (text) => {
const res = await api.post(
'/voice/speak',
{ text },
{ responseType: 'blob', timeout: 60_000 },
)
return res.data // audio/wav Blob
},
}
// ───────────────────────────────────────────────────
// TOOLS
// ───────────────────────────────────────────────────
export const toolsAPI = {
/**
* Execute a tool directly.
* @param {string} toolName
* @param {string} argument
*/
executeTool: async (toolName, argument) => {
const res = await api.post('/tools/execute', {
tool_name: toolName,
argument,
})
return res.data
},
listTools: async () => {
const res = await api.get('/tools/list')
return res.data
},
}
// ───────────────────────────────────────────────────
// SESSIONS
// ───────────────────────────────────────────────────
export const sessionsAPI = {
listSessions: async () => {
const res = await api.get('/sessions/')
return res.data
},
deleteSession: async (sessionId) => {
const res = await api.delete(`/sessions/${sessionId}`)
return res.data
},
renameSession: async (sessionId, title) => {
const res = await api.patch(`/sessions/${sessionId}`, { title })
return res.data
},
}
// ───────────────────────────────────────────────────
// HEALTH
// ───────────────────────────────────────────────────
export const healthAPI = {
check: async () => {
const res = await api.get('/health')
return res.data
},
}
export default api