12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628 |
- import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
- import { convertOpenApiToToolPayload } from '$lib/utils';
- import { getOpenAIModelsDirect } from './openai';
- import { parse } from 'yaml';
- import { toast } from 'svelte-sonner';
- export const getModels = async (
- token: string = '',
- connections: object | null = null,
- base: boolean = false
- ) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/models${base ? '/base' : ''}`, {
- method: 'GET',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- error = err;
- console.error(err);
- return null;
- });
- if (error) {
- throw error;
- }
- let models = res?.data ?? [];
- if (connections && !base) {
- let localModels = [];
- if (connections) {
- const OPENAI_API_BASE_URLS = connections.OPENAI_API_BASE_URLS;
- const OPENAI_API_KEYS = connections.OPENAI_API_KEYS;
- const OPENAI_API_CONFIGS = connections.OPENAI_API_CONFIGS;
- const requests = [];
- for (const idx in OPENAI_API_BASE_URLS) {
- const url = OPENAI_API_BASE_URLS[idx];
- if (idx.toString() in OPENAI_API_CONFIGS) {
- const apiConfig = OPENAI_API_CONFIGS[idx.toString()] ?? {};
- const enable = apiConfig?.enable ?? true;
- const modelIds = apiConfig?.model_ids ?? [];
- if (enable) {
- if (modelIds.length > 0) {
- const modelList = {
- object: 'list',
- data: modelIds.map((modelId) => ({
- id: modelId,
- name: modelId,
- owned_by: 'openai',
- openai: { id: modelId },
- urlIdx: idx
- }))
- };
- requests.push(
- (async () => {
- return modelList;
- })()
- );
- } else {
- requests.push(
- (async () => {
- return await getOpenAIModelsDirect(url, OPENAI_API_KEYS[idx])
- .then((res) => {
- return res;
- })
- .catch((err) => {
- return {
- object: 'list',
- data: [],
- urlIdx: idx
- };
- });
- })()
- );
- }
- } else {
- requests.push(
- (async () => {
- return {
- object: 'list',
- data: [],
- urlIdx: idx
- };
- })()
- );
- }
- }
- }
- const responses = await Promise.all(requests);
- for (const idx in responses) {
- const response = responses[idx];
- const apiConfig = OPENAI_API_CONFIGS[idx.toString()] ?? {};
- let models = Array.isArray(response) ? response : (response?.data ?? []);
- models = models.map((model) => ({ ...model, openai: { id: model.id }, urlIdx: idx }));
- const prefixId = apiConfig.prefix_id;
- if (prefixId) {
- for (const model of models) {
- model.id = `${prefixId}.${model.id}`;
- }
- }
- const tags = apiConfig.tags;
- if (tags) {
- for (const model of models) {
- model.tags = tags;
- }
- }
- localModels = localModels.concat(models);
- }
- }
- models = models.concat(
- localModels.map((model) => ({
- ...model,
- name: model?.name ?? model?.id,
- direct: true
- }))
- );
- // Remove duplicates
- const modelsMap = {};
- for (const model of models) {
- modelsMap[model.id] = model;
- }
- models = Object.values(modelsMap);
- }
- return models;
- };
- type ChatCompletedForm = {
- model: string;
- messages: string[];
- chat_id: string;
- session_id: string;
- };
- export const chatCompleted = async (token: string, body: ChatCompletedForm) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/chat/completed`, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- },
- body: JSON.stringify(body)
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- } else {
- error = err;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- type ChatActionForm = {
- model: string;
- messages: string[];
- chat_id: string;
- };
- export const chatAction = async (token: string, action_id: string, body: ChatActionForm) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/chat/actions/${action_id}`, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- },
- body: JSON.stringify(body)
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- } else {
- error = err;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const stopTask = async (token: string, id: string) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/tasks/stop/${id}`, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- } else {
- error = err;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const getTaskIdsByChatId = async (token: string, chat_id: string) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/tasks/chat/${chat_id}`, {
- method: 'GET',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- } else {
- error = err;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const getToolServerData = async (token: string, url: string) => {
- let error = null;
- const res = await fetch(`${url}`, {
- method: 'GET',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- }
- })
- .then(async (res) => {
- // Check if URL ends with .yaml or .yml to determine format
- if (url.toLowerCase().endsWith('.yaml') || url.toLowerCase().endsWith('.yml')) {
- if (!res.ok) throw await res.text();
- const text = await res.text();
- return parse(text);
- } else {
- if (!res.ok) throw await res.json();
- return res.json();
- }
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- } else {
- error = err;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- const data = {
- openapi: res,
- info: res.info,
- specs: convertOpenApiToToolPayload(res)
- };
- console.log(data);
- return data;
- };
- export const getToolServersData = async (i18n, servers: object[]) => {
- return (
- await Promise.all(
- servers
- .filter((server) => server?.config?.enable)
- .map(async (server) => {
- const data = await getToolServerData(
- (server?.auth_type ?? 'bearer') === 'bearer' ? server?.key : localStorage.token,
- (server?.path ?? '').includes('://')
- ? server?.path
- : `${server?.url}${(server?.path ?? '').startsWith('/') ? '' : '/'}${server?.path}`
- ).catch((err) => {
- toast.error(
- i18n.t(`Failed to connect to {{URL}} OpenAPI tool server`, {
- URL: (server?.path ?? '').includes('://')
- ? server?.path
- : `${server?.url}${(server?.path ?? '').startsWith('/') ? '' : '/'}${server?.path}`
- })
- );
- return null;
- });
- if (data) {
- const { openapi, info, specs } = data;
- return {
- url: server?.url,
- openapi: openapi,
- info: info,
- specs: specs
- };
- }
- })
- )
- ).filter((server) => server);
- };
- export const executeToolServer = async (
- token: string,
- url: string,
- name: string,
- params: Record<string, any>,
- serverData: { openapi: any; info: any; specs: any }
- ) => {
- let error = null;
- try {
- // Find the matching operationId in the OpenAPI spec
- const matchingRoute = Object.entries(serverData.openapi.paths).find(([_, methods]) =>
- Object.entries(methods as any).some(([__, operation]: any) => operation.operationId === name)
- );
- if (!matchingRoute) {
- throw new Error(`No matching route found for operationId: ${name}`);
- }
- const [routePath, methods] = matchingRoute;
- const methodEntry = Object.entries(methods as any).find(
- ([_, operation]: any) => operation.operationId === name
- );
- if (!methodEntry) {
- throw new Error(`No matching method found for operationId: ${name}`);
- }
- const [httpMethod, operation]: [string, any] = methodEntry;
- // Split parameters by type
- const pathParams: Record<string, any> = {};
- const queryParams: Record<string, any> = {};
- let bodyParams: any = {};
- if (operation.parameters) {
- operation.parameters.forEach((param: any) => {
- const paramName = param.name;
- const paramIn = param.in;
- if (params.hasOwnProperty(paramName)) {
- if (paramIn === 'path') {
- pathParams[paramName] = params[paramName];
- } else if (paramIn === 'query') {
- queryParams[paramName] = params[paramName];
- }
- }
- });
- }
- let finalUrl = `${url}${routePath}`;
- // Replace path parameters (`{param}`)
- Object.entries(pathParams).forEach(([key, value]) => {
- finalUrl = finalUrl.replace(new RegExp(`{${key}}`, 'g'), encodeURIComponent(value));
- });
- // Append query parameters to URL if any
- if (Object.keys(queryParams).length > 0) {
- const queryString = new URLSearchParams(
- Object.entries(queryParams).map(([k, v]) => [k, String(v)])
- ).toString();
- finalUrl += `?${queryString}`;
- }
- // Handle requestBody composite
- if (operation.requestBody && operation.requestBody.content) {
- const contentType = Object.keys(operation.requestBody.content)[0];
- if (params !== undefined) {
- bodyParams = params;
- } else {
- // Optional: Fallback or explicit error if body is expected but not provided
- throw new Error(`Request body expected for operation '${name}' but none found.`);
- }
- }
- // Prepare headers and request options
- const headers: Record<string, string> = {
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- };
- let requestOptions: RequestInit = {
- method: httpMethod.toUpperCase(),
- headers
- };
- if (['post', 'put', 'patch'].includes(httpMethod.toLowerCase()) && operation.requestBody) {
- requestOptions.body = JSON.stringify(bodyParams);
- }
- const res = await fetch(finalUrl, requestOptions);
- if (!res.ok) {
- const resText = await res.text();
- throw new Error(`HTTP error! Status: ${res.status}. Message: ${resText}`);
- }
- return await res.json();
- } catch (err: any) {
- error = err.message;
- console.error('API Request Error:', error);
- return { error };
- }
- };
- export const getTaskConfig = async (token: string = '') => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/tasks/config`, {
- method: 'GET',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const updateTaskConfig = async (token: string, config: object) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/tasks/config/update`, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- },
- body: JSON.stringify(config)
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- } else {
- error = err;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const generateTitle = async (
- token: string = '',
- model: string,
- messages: object[],
- chat_id?: string
- ) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/tasks/title/completions`, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- },
- body: JSON.stringify({
- model: model,
- messages: messages,
- ...(chat_id && { chat_id: chat_id })
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- try {
- // Step 1: Safely extract the response string
- const response = res?.choices[0]?.message?.content ?? '';
- // Step 2: Attempt to fix common JSON format issues like single quotes
- const sanitizedResponse = response.replace(/['‘’`]/g, '"'); // Convert single quotes to double quotes for valid JSON
- // Step 3: Find the relevant JSON block within the response
- const jsonStartIndex = sanitizedResponse.indexOf('{');
- const jsonEndIndex = sanitizedResponse.lastIndexOf('}');
- // Step 4: Check if we found a valid JSON block (with both `{` and `}`)
- if (jsonStartIndex !== -1 && jsonEndIndex !== -1) {
- const jsonResponse = sanitizedResponse.substring(jsonStartIndex, jsonEndIndex + 1);
- // Step 5: Parse the JSON block
- const parsed = JSON.parse(jsonResponse);
- // Step 6: If there's a "tags" key, return the tags array; otherwise, return an empty array
- if (parsed && parsed.title) {
- return parsed.title;
- } else {
- return null;
- }
- }
- // If no valid JSON block found, return an empty array
- return null;
- } catch (e) {
- // Catch and safely return empty array on any parsing errors
- console.error('Failed to parse response: ', e);
- return null;
- }
- };
- export const generateFollowUps = async (
- token: string = '',
- model: string,
- messages: string,
- chat_id?: string
- ) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/tasks/follow_ups/completions`, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- },
- body: JSON.stringify({
- model: model,
- messages: messages,
- ...(chat_id && { chat_id: chat_id })
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- try {
- // Step 1: Safely extract the response string
- const response = res?.choices[0]?.message?.content ?? '';
- // Step 2: Attempt to fix common JSON format issues like single quotes
- const sanitizedResponse = response.replace(/['‘’`]/g, '"'); // Convert single quotes to double quotes for valid JSON
- // Step 3: Find the relevant JSON block within the response
- const jsonStartIndex = sanitizedResponse.indexOf('{');
- const jsonEndIndex = sanitizedResponse.lastIndexOf('}');
- // Step 4: Check if we found a valid JSON block (with both `{` and `}`)
- if (jsonStartIndex !== -1 && jsonEndIndex !== -1) {
- const jsonResponse = sanitizedResponse.substring(jsonStartIndex, jsonEndIndex + 1);
- // Step 5: Parse the JSON block
- const parsed = JSON.parse(jsonResponse);
- // Step 6: If there's a "follow_ups" key, return the follow_ups array; otherwise, return an empty array
- if (parsed && parsed.follow_ups) {
- return Array.isArray(parsed.follow_ups) ? parsed.follow_ups : [];
- } else {
- return [];
- }
- }
- // If no valid JSON block found, return an empty array
- return [];
- } catch (e) {
- // Catch and safely return empty array on any parsing errors
- console.error('Failed to parse response: ', e);
- return [];
- }
- };
- export const generateTags = async (
- token: string = '',
- model: string,
- messages: string,
- chat_id?: string
- ) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/tasks/tags/completions`, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- },
- body: JSON.stringify({
- model: model,
- messages: messages,
- ...(chat_id && { chat_id: chat_id })
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- try {
- // Step 1: Safely extract the response string
- const response = res?.choices[0]?.message?.content ?? '';
- // Step 2: Attempt to fix common JSON format issues like single quotes
- const sanitizedResponse = response.replace(/['‘’`]/g, '"'); // Convert single quotes to double quotes for valid JSON
- // Step 3: Find the relevant JSON block within the response
- const jsonStartIndex = sanitizedResponse.indexOf('{');
- const jsonEndIndex = sanitizedResponse.lastIndexOf('}');
- // Step 4: Check if we found a valid JSON block (with both `{` and `}`)
- if (jsonStartIndex !== -1 && jsonEndIndex !== -1) {
- const jsonResponse = sanitizedResponse.substring(jsonStartIndex, jsonEndIndex + 1);
- // Step 5: Parse the JSON block
- const parsed = JSON.parse(jsonResponse);
- // Step 6: If there's a "tags" key, return the tags array; otherwise, return an empty array
- if (parsed && parsed.tags) {
- return Array.isArray(parsed.tags) ? parsed.tags : [];
- } else {
- return [];
- }
- }
- // If no valid JSON block found, return an empty array
- return [];
- } catch (e) {
- // Catch and safely return empty array on any parsing errors
- console.error('Failed to parse response: ', e);
- return [];
- }
- };
- export const generateEmoji = async (
- token: string = '',
- model: string,
- prompt: string,
- chat_id?: string
- ) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/tasks/emoji/completions`, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- },
- body: JSON.stringify({
- model: model,
- prompt: prompt,
- ...(chat_id && { chat_id: chat_id })
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- const response = res?.choices[0]?.message?.content.replace(/["']/g, '') ?? null;
- if (response) {
- if (/\p{Extended_Pictographic}/u.test(response)) {
- return response.match(/\p{Extended_Pictographic}/gu)[0];
- }
- }
- return null;
- };
- export const generateQueries = async (
- token: string = '',
- model: string,
- messages: object[],
- prompt: string,
- type?: string = 'web_search'
- ) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/tasks/queries/completions`, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- },
- body: JSON.stringify({
- model: model,
- messages: messages,
- prompt: prompt,
- type: type
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- // Step 1: Safely extract the response string
- const response = res?.choices[0]?.message?.content ?? '';
- try {
- const jsonStartIndex = response.indexOf('{');
- const jsonEndIndex = response.lastIndexOf('}');
- if (jsonStartIndex !== -1 && jsonEndIndex !== -1) {
- const jsonResponse = response.substring(jsonStartIndex, jsonEndIndex + 1);
- // Step 5: Parse the JSON block
- const parsed = JSON.parse(jsonResponse);
- // Step 6: If there's a "queries" key, return the queries array; otherwise, return an empty array
- if (parsed && parsed.queries) {
- return Array.isArray(parsed.queries) ? parsed.queries : [];
- } else {
- return [];
- }
- }
- // If no valid JSON block found, return response as is
- return [response];
- } catch (e) {
- // Catch and safely return empty array on any parsing errors
- console.error('Failed to parse response: ', e);
- return [response];
- }
- };
- export const generateAutoCompletion = async (
- token: string = '',
- model: string,
- prompt: string,
- messages?: object[],
- type: string = 'search query'
- ) => {
- const controller = new AbortController();
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/tasks/auto/completions`, {
- signal: controller.signal,
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- },
- body: JSON.stringify({
- model: model,
- prompt: prompt,
- ...(messages && { messages: messages }),
- type: type,
- stream: false
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- const response = res?.choices[0]?.message?.content ?? '';
- try {
- const jsonStartIndex = response.indexOf('{');
- const jsonEndIndex = response.lastIndexOf('}');
- if (jsonStartIndex !== -1 && jsonEndIndex !== -1) {
- const jsonResponse = response.substring(jsonStartIndex, jsonEndIndex + 1);
- // Step 5: Parse the JSON block
- const parsed = JSON.parse(jsonResponse);
- // Step 6: If there's a "queries" key, return the queries array; otherwise, return an empty array
- if (parsed && parsed.text) {
- return parsed.text;
- } else {
- return '';
- }
- }
- // If no valid JSON block found, return response as is
- return response;
- } catch (e) {
- // Catch and safely return empty array on any parsing errors
- console.error('Failed to parse response: ', e);
- return response;
- }
- };
- export const generateMoACompletion = async (
- token: string = '',
- model: string,
- prompt: string,
- responses: string[]
- ) => {
- const controller = new AbortController();
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/tasks/moa/completions`, {
- signal: controller.signal,
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- },
- body: JSON.stringify({
- model: model,
- prompt: prompt,
- responses: responses,
- stream: true
- })
- }).catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return [res, controller];
- };
- export const getPipelinesList = async (token: string = '') => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/pipelines/list`, {
- method: 'GET',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- let pipelines = res?.data ?? [];
- return pipelines;
- };
- export const uploadPipeline = async (token: string, file: File, urlIdx: string) => {
- let error = null;
- // Create a new FormData object to handle the file upload
- const formData = new FormData();
- formData.append('file', file);
- formData.append('urlIdx', urlIdx);
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/pipelines/upload`, {
- method: 'POST',
- headers: {
- ...(token && { authorization: `Bearer ${token}` })
- // 'Content-Type': 'multipart/form-data' is not needed as Fetch API will set it automatically
- },
- body: formData
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- } else {
- error = err;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const downloadPipeline = async (token: string, url: string, urlIdx: string) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/pipelines/add`, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- },
- body: JSON.stringify({
- url: url,
- urlIdx: urlIdx
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- } else {
- error = err;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const deletePipeline = async (token: string, id: string, urlIdx: string) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/pipelines/delete`, {
- method: 'DELETE',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- },
- body: JSON.stringify({
- id: id,
- urlIdx: urlIdx
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- } else {
- error = err;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const getPipelines = async (token: string, urlIdx?: string) => {
- let error = null;
- const searchParams = new URLSearchParams();
- if (urlIdx !== undefined) {
- searchParams.append('urlIdx', urlIdx);
- }
- const res = await fetch(`${WEBUI_BASE_URL}/api/v1/pipelines/?${searchParams.toString()}`, {
- method: 'GET',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- let pipelines = res?.data ?? [];
- return pipelines;
- };
- export const getPipelineValves = async (token: string, pipeline_id: string, urlIdx: string) => {
- let error = null;
- const searchParams = new URLSearchParams();
- if (urlIdx !== undefined) {
- searchParams.append('urlIdx', urlIdx);
- }
- const res = await fetch(
- `${WEBUI_BASE_URL}/api/v1/pipelines/${pipeline_id}/valves?${searchParams.toString()}`,
- {
- method: 'GET',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- }
- }
- )
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const getPipelineValvesSpec = async (token: string, pipeline_id: string, urlIdx: string) => {
- let error = null;
- const searchParams = new URLSearchParams();
- if (urlIdx !== undefined) {
- searchParams.append('urlIdx', urlIdx);
- }
- const res = await fetch(
- `${WEBUI_BASE_URL}/api/v1/pipelines/${pipeline_id}/valves/spec?${searchParams.toString()}`,
- {
- method: 'GET',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- }
- }
- )
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const updatePipelineValves = async (
- token: string = '',
- pipeline_id: string,
- valves: object,
- urlIdx: string
- ) => {
- let error = null;
- const searchParams = new URLSearchParams();
- if (urlIdx !== undefined) {
- searchParams.append('urlIdx', urlIdx);
- }
- const res = await fetch(
- `${WEBUI_BASE_URL}/api/v1/pipelines/${pipeline_id}/valves/update?${searchParams.toString()}`,
- {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- ...(token && { authorization: `Bearer ${token}` })
- },
- body: JSON.stringify(valves)
- }
- )
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- if ('detail' in err) {
- error = err.detail;
- } else {
- error = err;
- }
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const getUsage = async (token: string = '') => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/usage`, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- ...(token && { Authorization: `Bearer ${token}` })
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const getBackendConfig = async () => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/config`, {
- method: 'GET',
- credentials: 'include',
- headers: {
- 'Content-Type': 'application/json'
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const getChangelog = async () => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/changelog`, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json'
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const getVersionUpdates = async (token: string) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/version/updates`, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const getModelFilterConfig = async (token: string) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/config/model/filter`, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const updateModelFilterConfig = async (
- token: string,
- enabled: boolean,
- models: string[]
- ) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/config/model/filter`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- },
- body: JSON.stringify({
- enabled: enabled,
- models: models
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const getWebhookUrl = async (token: string) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/webhook`, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res.url;
- };
- export const updateWebhookUrl = async (token: string, url: string) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/webhook`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- },
- body: JSON.stringify({
- url: url
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res.url;
- };
- export const getCommunitySharingEnabledStatus = async (token: string) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/community_sharing`, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const toggleCommunitySharingEnabledStatus = async (token: string) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/community_sharing/toggle`, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err.detail;
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
- export const getModelConfig = async (token: string): Promise<GlobalModelConfig> => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/config/models`, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res.models;
- };
- export interface ModelConfig {
- id: string;
- name: string;
- meta: ModelMeta;
- base_model_id?: string;
- params: ModelParams;
- }
- export interface ModelMeta {
- toolIds: never[];
- description?: string;
- capabilities?: object;
- profile_image_url?: string;
- }
- export interface ModelParams {}
- export type GlobalModelConfig = ModelConfig[];
- export const updateModelConfig = async (token: string, config: GlobalModelConfig) => {
- let error = null;
- const res = await fetch(`${WEBUI_BASE_URL}/api/config/models`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`
- },
- body: JSON.stringify({
- models: config
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- console.error(err);
- error = err;
- return null;
- });
- if (error) {
- throw error;
- }
- return res;
- };
|