From 6f1a7383e9b95b1f6d44e3df7ce1d485a06a2a17 Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Wed, 6 May 2026 03:47:52 +0200 Subject: [PATCH] Add chat API service functions --- src/App.jsx | 10 ++++ src/chatApi.js | 143 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 src/chatApi.js diff --git a/src/App.jsx b/src/App.jsx index 1cf7033..4313cb5 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -38,6 +38,16 @@ import { } from './backendApi' import { sanitizeChatTitle, splitThinkBlocks } from './chatText' import { buildModelPickerOptions } from './modelPicker' +import { + fetchLocalLibraryContext, + fetchModelCapabilities, + fetchStartupOllamaStatus, + fetchWebSearchContext, + postChatMessage, + postRegenerateMessage, + prepareStartupModels, + requestGeneratedTitle, +} from './chatApi' import { loadStoredWebsearchEngines, normalizeWebsearchEngines, diff --git a/src/chatApi.js b/src/chatApi.js new file mode 100644 index 0000000..80f7a00 --- /dev/null +++ b/src/chatApi.js @@ -0,0 +1,143 @@ +import { expectBackendJson } from './backendApi' + +export async function fetchModelCapabilities(apiBase, modelName, signal) { + const response = await fetch( + `${apiBase}/models/capabilities?name=${encodeURIComponent(modelName)}`, + { signal } + ) + return expectBackendJson(response) +} + +export async function fetchStartupOllamaStatus(apiBase) { + const response = await fetch(`${apiBase}/ollama/startup-status`) + return expectBackendJson(response) +} + +export async function prepareStartupModels(apiBase) { + const response = await fetch(`${apiBase}/startup/prepare-models`, { method: 'POST' }) + return expectBackendJson(response) +} + +export async function fetchLocalLibraryContext(apiBase, slug, prompt, signal) { + if (!slug) return { contextBlock: null, sources: [] } + + const response = await fetch(`${apiBase}/libraries/${slug}/context`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + signal, + body: JSON.stringify({ + prompt, + top_k: 5, + }), + }) + const data = await response.json() + return { + contextBlock: typeof data?.context_block === 'string' && data.context_block.trim() + ? data.context_block.trim() + : null, + sources: Array.isArray(data?.sources) ? data.sources : [], + } +} + +export async function fetchWebSearchContext({ + apiBase, + engines, + historyLimit = 8, + messages, + model, + prompt, + searxUrl, + signal, +}) { + const response = await fetch(`${apiBase}/websearch`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + signal, + body: JSON.stringify({ + prompt, + model, + messages, + history_limit: historyLimit, + searx_url: searxUrl || null, + engines: Array.isArray(engines) ? engines : null, + }), + }) + const data = await response.json() + return { + contextBlock: typeof data?.context_block === 'string' && data.context_block.trim() + ? data.context_block.trim() + : null, + sources: Array.isArray(data?.sources) ? data.sources : [], + } +} + +export function postChatMessage({ + apiBase, + attachments, + enrichedMessage, + message, + model, + sessionId, + signal, + sources, + stream, + transcriptionModel, + visionModel, +}) { + return fetch(`${apiBase}/chat`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + signal, + body: JSON.stringify({ + session_id: sessionId, + model, + message, + enriched_message: enrichedMessage, + stream, + sources: sources || [], + attachments, + vision_model: visionModel || null, + transcription_model: transcriptionModel || null, + }), + }) +} + +export function postRegenerateMessage({ + apiBase, + enrichedMessage, + index, + model, + sessionId, + signal, + sources, + stream, + transcriptionModel, + visionModel, +}) { + return fetch(`${apiBase}/sessions/${sessionId}/regenerate`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + signal, + body: JSON.stringify({ + index, + model, + stream, + enriched_message: enrichedMessage, + sources: sources || [], + vision_model: visionModel || null, + transcription_model: transcriptionModel || null, + }), + }) +} + +export function requestGeneratedTitle({ apiBase, message, model, sessionId }) { + return fetch(`${apiBase}/generate-title`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + session_id: sessionId, + message, + model, + }), + }) +}