export const DEFAULT_BACKEND_URL = ''; export const DEFAULT_LIVE_DEBUG_URL = 'http://localhost:8001'; async function fetchJson(url, options) { const response = await fetch(url, options); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } return response.json(); } function tracePayload(testRun, nodeId = '', llmSessionId = '') { return { ...(testRun?.testRunId ? { test_run_id: testRun.testRunId, workflow_name: testRun.workflowName || 'workflow', node_id: nodeId, } : {}), ...(llmSessionId ? { llm_session_id: llmSessionId } : {}), }; } export async function startTestRun(backendUrl, workflowName) { return fetchJson(`${backendUrl}/start-test-run`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ workflow_name: workflowName || 'workflow', }), }); } export async function startTranscriptLog(backendUrl, workflowName) { return fetchJson(`${backendUrl}/start-transcript-log`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ workflow_name: workflowName || 'workflow', }), }); } export async function appendTranscriptLog(backendUrl, logPath, role, text) { return fetchJson(`${backendUrl}/append-transcript-log`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ log_path: logPath, role, text, }), }); } export async function getDeepinfraKeyStatus(backendUrl) { return fetchJson(`${backendUrl}/deepinfra-key-status`, { method: 'GET', headers: { Accept: 'application/json', }, mode: 'cors', credentials: 'omit', }); } export async function saveDeepinfraKey(backendUrl, apiKey) { return fetchJson(`${backendUrl}/save-deepinfra-key`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ api_key: apiKey, }), }); } export async function loadConfig() { try { const config = await fetchJson(`/config.json?t=${Date.now()}`); return { backendUrl: config.backendUrl ?? DEFAULT_BACKEND_URL, liveDebugUrl: config.liveDebugUrl || config.live_debug_url || DEFAULT_LIVE_DEBUG_URL, llmProvider: config.llmProvider || config.provider || '', deepinfraApiKey: config.deepinfraApiKey || config.deepinfra_api_key || '', demo: Boolean(config.demo), }; } catch (error) { console.error('Failed to load config:', error); return { backendUrl: DEFAULT_BACKEND_URL, liveDebugUrl: DEFAULT_LIVE_DEBUG_URL, llmProvider: '', deepinfraApiKey: '', demo: false, }; } } export async function loadDefaultWorkflow() { return fetchJson(`/default-workflow?t=${Date.now()}`); } export async function saveDefaultWorkflow(backendUrl, document) { return fetchJson(`${backendUrl}/default-workflow`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ document, }), }); } export async function loadPresets() { try { const presets = await fetchJson(`/presets.json?t=${Date.now()}`); return { default: presets.system_prompts || [], custom: presets.custom_presets || [], }; } catch (error) { console.error('Failed to load presets:', error); return { default: [], custom: [], }; } } export async function saveCustomPreset(backendUrl, name, text) { const response = await fetchJson(`${backendUrl}/save-preset`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, body: JSON.stringify({ name, text, }), }); return Boolean(response.success); } export async function requestLLM( backendUrl, systemPrompt, userPrompt, testRun = null, nodeId = '', provider = 'ollama', llmSessionId = '', assistantRole = '', ) { const response = await fetchJson(`${backendUrl}/request-llm`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ system_prompt: systemPrompt, user_prompt: userPrompt, provider, ...tracePayload(testRun, nodeId, llmSessionId), }), }); return response.response || ''; } export async function paraphraseText( backendUrl, text, messageType = 'message', testRun = null, nodeId = '', provider = 'ollama', llmSessionId = '', assistantRole = '', ) { const response = await fetchJson(`${backendUrl}/paraphrase-text`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ text, message_type: messageType, language: 'русский', provider, assistant_role: assistantRole, ...tracePayload(testRun, nodeId, llmSessionId), }), }); return response.text || text || ''; } export async function extractMemoryFieldRequest( backendUrl, answer, key, instruction, question, language = 'русский', testRun = null, nodeId = '', provider = 'ollama', llmSessionId = '', ) { return fetchJson(`${backendUrl}/extract-memory-field`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ answer, key, instruction, question, language, provider, ...tracePayload(testRun, nodeId, llmSessionId), }), }); } export async function classifyRequest( backendUrl, question, answer, options, testRun = null, nodeId = '', provider = 'ollama', llmSessionId = '', ) { const response = await fetchJson(`${backendUrl}/classify`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ question, answer, options, provider, ...tracePayload(testRun, nodeId, llmSessionId), }), }); return response.classification || ''; } export async function uploadContextFile(backendUrl, filename, contentBase64) { return fetchJson(`${backendUrl}/upload-context`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ filename, content_base64: contentBase64, }), }); } export async function answerFromContext( backendUrl, question, contextId, source = 'uploaded', language = 'русский', contextPath = '', testRun = null, nodeId = '', provider = 'ollama', llmSessionId = '', ) { const response = await fetchJson(`${backendUrl}/answer-from-context`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ question, context_id: contextId || '', context_path: contextPath || '', source, language, provider, ...tracePayload(testRun, nodeId, llmSessionId), }), }); return response.answer || ''; } export async function simulateUserAnswer( backendUrl, provider, rolePrompt, question, transcript, testRun = null, llmSessionId = '', ) { const response = await fetchJson(`${backendUrl}/simulate-user-answer`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ provider, role_prompt: rolePrompt, question, transcript, ...tracePayload(testRun, '', llmSessionId), }), }); if (response.error) { throw new Error(response.error); } return response.answer || ''; } export async function evaluateAssistantAnswer( backendUrl, question, answer, transcript, testRun = null, messageType = 'answer', provider = 'ollama', llmSessionId = '', ) { return fetchJson(`${backendUrl}/evaluate-assistant-answer`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ question, answer, transcript, message_type: messageType, provider, ...tracePayload(testRun, '', llmSessionId), }), }); } export async function getLlmSessionLog(backendUrl, llmSessionId) { return fetchJson(`${backendUrl}/get-llm-session-log`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, mode: 'cors', credentials: 'omit', body: JSON.stringify({ llm_session_id: llmSessionId, }), }); }