feat: add copilot setting to config
refactor: move getConfig to actions, extracted Settings
This commit is contained in:
parent
d788ca8eba
commit
79d4d87f24
10 changed files with 140 additions and 113 deletions
|
@ -1,54 +1,55 @@
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import {parse, stringify} from "smol-toml";
|
import { parse, stringify } from 'smol-toml';
|
||||||
|
|
||||||
const configFileName = 'config.toml';
|
const configFileName = 'config.toml';
|
||||||
|
|
||||||
interface Config {
|
interface Config {
|
||||||
GENERAL: {
|
GENERAL: {
|
||||||
PORT: number;
|
PORT: number;
|
||||||
SIMILARITY_MEASURE: string;
|
SIMILARITY_MEASURE: string;
|
||||||
};
|
ENABLE_COPILOT: boolean;
|
||||||
API_KEYS: {
|
};
|
||||||
OPENAI: string;
|
API_KEYS: {
|
||||||
GROQ: string;
|
OPENAI: string;
|
||||||
};
|
GROQ: string;
|
||||||
API_ENDPOINTS: {
|
};
|
||||||
SEARXNG: string;
|
API_ENDPOINTS: {
|
||||||
OLLAMA: string;
|
SEARXNG: string;
|
||||||
};
|
OLLAMA: string;
|
||||||
MODELS: [
|
};
|
||||||
{
|
MODELS: [
|
||||||
"name": string;
|
{
|
||||||
"api_key": string;
|
name: string;
|
||||||
"base_url": string;
|
api_key: string;
|
||||||
"provider": string;
|
base_url: string;
|
||||||
}
|
provider: string;
|
||||||
];
|
},
|
||||||
EMBEDDINGS: [
|
];
|
||||||
{
|
EMBEDDINGS: [
|
||||||
"name": string;
|
{
|
||||||
"model": string;
|
name: string;
|
||||||
"api_key": string;
|
model: string;
|
||||||
"base_url": string;
|
api_key: string;
|
||||||
"provider": string;
|
base_url: string;
|
||||||
}
|
provider: string;
|
||||||
];
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
type RecursivePartial<T> = {
|
type RecursivePartial<T> = {
|
||||||
[P in keyof T]?: RecursivePartial<T[P]>;
|
[P in keyof T]?: RecursivePartial<T[P]>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadConfig = () =>
|
const loadConfig = () =>
|
||||||
parse(
|
parse(
|
||||||
fs.readFileSync(path.join(__dirname, `../${configFileName}`), 'utf-8'),
|
fs.readFileSync(path.join(__dirname, `../${configFileName}`), 'utf-8'),
|
||||||
) as any as Config;
|
) as any as Config;
|
||||||
|
|
||||||
export const getPort = () => loadConfig().GENERAL.PORT;
|
export const getPort = () => loadConfig().GENERAL.PORT;
|
||||||
|
|
||||||
export const getSimilarityMeasure = () =>
|
export const getSimilarityMeasure = () =>
|
||||||
loadConfig().GENERAL.SIMILARITY_MEASURE;
|
loadConfig().GENERAL.SIMILARITY_MEASURE;
|
||||||
|
|
||||||
export const getOpenaiApiKey = () => loadConfig().API_KEYS.OPENAI;
|
export const getOpenaiApiKey = () => loadConfig().API_KEYS.OPENAI;
|
||||||
|
|
||||||
|
@ -62,18 +63,17 @@ export const getCustomModels = () => loadConfig().MODELS;
|
||||||
|
|
||||||
export const getCustomEmbeddingModels = () => loadConfig().EMBEDDINGS;
|
export const getCustomEmbeddingModels = () => loadConfig().EMBEDDINGS;
|
||||||
|
|
||||||
|
export const getCopilotEnabled = () => loadConfig().GENERAL.ENABLE_COPILOT;
|
||||||
|
|
||||||
export const updateConfig = (config: RecursivePartial<Config>) => {
|
export const updateConfig = (config: RecursivePartial<Config>) => {
|
||||||
const currentConfig = loadConfig();
|
const currentConfig = loadConfig();
|
||||||
|
|
||||||
const updatedConfig = {
|
const updatedConfig = {
|
||||||
...currentConfig,
|
...currentConfig,
|
||||||
...config
|
...config,
|
||||||
};
|
};
|
||||||
|
|
||||||
const toml = stringify(updatedConfig);
|
const toml = stringify(updatedConfig);
|
||||||
|
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(path.join(__dirname, `../${configFileName}`), toml);
|
||||||
path.join(__dirname, `../${configFileName}`),
|
|
||||||
toml,
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
getAvailableEmbeddingModelProviders,
|
getAvailableEmbeddingModelProviders,
|
||||||
} from '../lib/providers';
|
} from '../lib/providers';
|
||||||
import {
|
import {
|
||||||
|
getCopilotEnabled,
|
||||||
getGroqApiKey,
|
getGroqApiKey,
|
||||||
getOllamaApiEndpoint,
|
getOllamaApiEndpoint,
|
||||||
getOpenaiApiKey,
|
getOpenaiApiKey,
|
||||||
|
@ -38,6 +39,7 @@ router.get('/', async (_, res) => {
|
||||||
config['openaiApiKey'] = getOpenaiApiKey();
|
config['openaiApiKey'] = getOpenaiApiKey();
|
||||||
config['ollamaApiUrl'] = getOllamaApiEndpoint();
|
config['ollamaApiUrl'] = getOllamaApiEndpoint();
|
||||||
config['groqApiKey'] = getGroqApiKey();
|
config['groqApiKey'] = getGroqApiKey();
|
||||||
|
config['copilotEnabled'] = getCopilotEnabled();
|
||||||
|
|
||||||
res.status(200).json(config);
|
res.status(200).json(config);
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,7 +7,7 @@ import Chat from './Chat';
|
||||||
import EmptyChat from './EmptyChat';
|
import EmptyChat from './EmptyChat';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { useSearchParams } from 'next/navigation';
|
import { useSearchParams } from 'next/navigation';
|
||||||
import { getSuggestions } from '@/lib/actions';
|
import { getConfig, getSuggestions } from '@/lib/actions';
|
||||||
|
|
||||||
export type Message = {
|
export type Message = {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -156,6 +156,15 @@ const ChatWindow = () => {
|
||||||
messagesRef.current = messages;
|
messagesRef.current = messages;
|
||||||
}, [messages]);
|
}, [messages]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchConfig = async () => {
|
||||||
|
const config = await getConfig();
|
||||||
|
localStorage.setItem('copilotEnabled', config.copilotEnabled.toString());
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchConfig();
|
||||||
|
});
|
||||||
|
|
||||||
const sendMessage = async (message: string) => {
|
const sendMessage = async (message: string) => {
|
||||||
if (loading) return;
|
if (loading) return;
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
|
@ -12,8 +12,9 @@ const EmptyChatMessageInput = ({
|
||||||
focusMode: string;
|
focusMode: string;
|
||||||
setFocusMode: (mode: string) => void;
|
setFocusMode: (mode: string) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const [copilotEnabled, setCopilotEnabled] = useState(false);
|
const [copilotToggled, setCopilotToggled] = useState(false);
|
||||||
const [message, setMessage] = useState('');
|
const [message, setMessage] = useState('');
|
||||||
|
const copilotEnabled = localStorage.getItem('copilotEnabled') === 'true';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
|
@ -45,10 +46,12 @@ const EmptyChatMessageInput = ({
|
||||||
{/* <Attach /> */}
|
{/* <Attach /> */}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center space-x-4 -mx-2">
|
<div className="flex flex-row items-center space-x-4 -mx-2">
|
||||||
<CopilotToggle
|
{copilotEnabled && (
|
||||||
copilotEnabled={copilotEnabled}
|
<CopilotToggle
|
||||||
setCopilotEnabled={setCopilotEnabled}
|
copilotToggled={copilotToggled}
|
||||||
/>
|
setCopilotToggled={setCopilotToggled}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
disabled={message.trim().length === 0}
|
disabled={message.trim().length === 0}
|
||||||
className="bg-[#24A0ED] text-white disabled:text-white/50 hover:bg-opacity-85 transition duration-100 disabled:bg-[#ececec21] rounded-full p-2"
|
className="bg-[#24A0ED] text-white disabled:text-white/50 hover:bg-opacity-85 transition duration-100 disabled:bg-[#ececec21] rounded-full p-2"
|
||||||
|
|
|
@ -7,11 +7,10 @@ import { cn } from '@/lib/utils';
|
||||||
import {
|
import {
|
||||||
BookCopy,
|
BookCopy,
|
||||||
Disc3,
|
Disc3,
|
||||||
Share,
|
|
||||||
Volume2,
|
|
||||||
StopCircle,
|
|
||||||
Layers3,
|
Layers3,
|
||||||
Plus,
|
Plus,
|
||||||
|
StopCircle,
|
||||||
|
Volume2,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import Markdown from 'markdown-to-jsx';
|
import Markdown from 'markdown-to-jsx';
|
||||||
import Copy from './MessageActions/Copy';
|
import Copy from './MessageActions/Copy';
|
||||||
|
@ -157,6 +156,7 @@ const MessageBox = ({
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
sendMessage(suggestion);
|
sendMessage(suggestion);
|
||||||
}}
|
}}
|
||||||
|
role="button"
|
||||||
className="cursor-pointer flex flex-row justify-between font-medium space-x-2 items-center"
|
className="cursor-pointer flex flex-row justify-between font-medium space-x-2 items-center"
|
||||||
>
|
>
|
||||||
<p className="transition duration-200 hover:text-[#24A0ED]">
|
<p className="transition duration-200 hover:text-[#24A0ED]">
|
||||||
|
|
|
@ -11,7 +11,7 @@ const MessageInput = ({
|
||||||
sendMessage: (message: string) => void;
|
sendMessage: (message: string) => void;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const [copilotEnabled, setCopilotEnabled] = useState(false);
|
const [copilotToggled, setCopilotToggled] = useState(false);
|
||||||
const [message, setMessage] = useState('');
|
const [message, setMessage] = useState('');
|
||||||
const [textareaRows, setTextareaRows] = useState(1);
|
const [textareaRows, setTextareaRows] = useState(1);
|
||||||
const [mode, setMode] = useState<'multi' | 'single'>('single');
|
const [mode, setMode] = useState<'multi' | 'single'>('single');
|
||||||
|
@ -57,8 +57,8 @@ const MessageInput = ({
|
||||||
{mode === 'single' && (
|
{mode === 'single' && (
|
||||||
<div className="flex flex-row items-center space-x-4">
|
<div className="flex flex-row items-center space-x-4">
|
||||||
<CopilotToggle
|
<CopilotToggle
|
||||||
copilotEnabled={copilotEnabled}
|
copilotToggled={copilotToggled}
|
||||||
setCopilotEnabled={setCopilotEnabled}
|
setCopilotToggled={setCopilotToggled}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
disabled={message.trim().length === 0 || loading}
|
disabled={message.trim().length === 0 || loading}
|
||||||
|
@ -73,8 +73,8 @@ const MessageInput = ({
|
||||||
<Attach />
|
<Attach />
|
||||||
<div className="flex flex-row items-center space-x-4">
|
<div className="flex flex-row items-center space-x-4">
|
||||||
<CopilotToggle
|
<CopilotToggle
|
||||||
copilotEnabled={copilotEnabled}
|
copilotToggled={copilotToggled}
|
||||||
setCopilotEnabled={setCopilotEnabled}
|
setCopilotToggled={setCopilotToggled}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
disabled={message.trim().length === 0 || loading}
|
disabled={message.trim().length === 0 || loading}
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
import {BadgePercent, ChevronDown, CopyPlus, Globe, Pencil, ScanEye, SwatchBook,} from 'lucide-react';
|
import {
|
||||||
import {cn} from '@/lib/utils';
|
BadgePercent,
|
||||||
import {Popover, Switch, Transition} from '@headlessui/react';
|
ChevronDown,
|
||||||
import {SiReddit, SiYoutube} from '@icons-pack/react-simple-icons';
|
CopyPlus,
|
||||||
import {Fragment} from 'react';
|
Globe,
|
||||||
|
Pencil,
|
||||||
|
ScanEye,
|
||||||
|
SwatchBook,
|
||||||
|
} from 'lucide-react';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
import { Popover, Switch, Transition } from '@headlessui/react';
|
||||||
|
import { SiReddit, SiYoutube } from '@icons-pack/react-simple-icons';
|
||||||
|
import { Fragment } from 'react';
|
||||||
|
|
||||||
export const Attach = () => {
|
export const Attach = () => {
|
||||||
return (
|
return (
|
||||||
|
@ -46,9 +54,9 @@ const focusModes = [
|
||||||
description: 'Search and watch videos',
|
description: 'Search and watch videos',
|
||||||
icon: (
|
icon: (
|
||||||
<SiYoutube
|
<SiYoutube
|
||||||
className="h-5 w-auto mr-0.5"
|
className="h-5 w-auto mr-0.5"
|
||||||
onPointerEnter={undefined}
|
onPointerEnter={undefined}
|
||||||
onPointerLeave={undefined}
|
onPointerLeave={undefined}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -58,9 +66,9 @@ const focusModes = [
|
||||||
description: 'Search for discussions and opinions',
|
description: 'Search for discussions and opinions',
|
||||||
icon: (
|
icon: (
|
||||||
<SiReddit
|
<SiReddit
|
||||||
className="h-5 w-auto mr-0.5"
|
className="h-5 w-auto mr-0.5"
|
||||||
onPointerEnter={undefined}
|
onPointerEnter={undefined}
|
||||||
onPointerLeave={undefined}
|
onPointerLeave={undefined}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -133,23 +141,23 @@ export const Focus = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CopilotToggle = ({
|
export const CopilotToggle = ({
|
||||||
copilotEnabled,
|
copilotToggled,
|
||||||
setCopilotEnabled,
|
setCopilotToggled,
|
||||||
}: {
|
}: {
|
||||||
copilotEnabled: boolean;
|
copilotToggled: boolean;
|
||||||
setCopilotEnabled: (enabled: boolean) => void;
|
setCopilotToggled: (enabled: boolean) => void;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className="group flex flex-row items-center space-x-1 active:scale-95 duration-200 transition cursor-pointer">
|
<div className="group flex flex-row items-center space-x-1 active:scale-95 duration-200 transition cursor-pointer">
|
||||||
<Switch
|
<Switch
|
||||||
checked={copilotEnabled}
|
checked={copilotToggled}
|
||||||
onChange={setCopilotEnabled}
|
onChange={setCopilotToggled}
|
||||||
className="bg-[#111111] border border-[#1C1C1C] relative inline-flex h-5 w-10 sm:h-6 sm:w-11 items-center rounded-full"
|
className="bg-[#111111] border border-[#1C1C1C] relative inline-flex h-5 w-10 sm:h-6 sm:w-11 items-center rounded-full"
|
||||||
>
|
>
|
||||||
<span className="sr-only">Copilot</span>
|
<span className="sr-only">Copilot</span>
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
copilotEnabled
|
copilotToggled
|
||||||
? 'translate-x-6 bg-[#24A0ED]'
|
? 'translate-x-6 bg-[#24A0ED]'
|
||||||
: 'translate-x-1 bg-white/50',
|
: 'translate-x-1 bg-white/50',
|
||||||
'inline-block h-3 w-3 sm:h-4 sm:w-4 transform rounded-full transition-all duration-200',
|
'inline-block h-3 w-3 sm:h-4 sm:w-4 transform rounded-full transition-all duration-200',
|
||||||
|
@ -157,10 +165,10 @@ export const CopilotToggle = ({
|
||||||
/>
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
<p
|
<p
|
||||||
onClick={() => setCopilotEnabled(!copilotEnabled)}
|
onClick={() => setCopilotToggled(!copilotToggled)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'text-xs font-medium transition-colors duration-150 ease-in-out',
|
'text-xs font-medium transition-colors duration-150 ease-in-out',
|
||||||
copilotEnabled
|
copilotToggled
|
||||||
? 'text-[#24A0ED]'
|
? 'text-[#24A0ED]'
|
||||||
: 'text-white/50 group-hover:text-white',
|
: 'text-white/50 group-hover:text-white',
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
import { Dialog, Transition } from '@headlessui/react';
|
import { Dialog, Transition } from '@headlessui/react';
|
||||||
import { CloudUpload, RefreshCcw, RefreshCw } from 'lucide-react';
|
import { CloudUpload, RefreshCcw, RefreshCw } from 'lucide-react';
|
||||||
import React, { Fragment, useEffect, useState } from 'react';
|
import React, { Fragment, useEffect, useState } from 'react';
|
||||||
|
import { Settings } from '@/types/Settings';
|
||||||
interface SettingsType {
|
import { getConfig } from '@/lib/actions';
|
||||||
chatModelProviders: {
|
|
||||||
[key: string]: string[];
|
|
||||||
};
|
|
||||||
embeddingModelProviders: {
|
|
||||||
[key: string]: string[];
|
|
||||||
};
|
|
||||||
openaiApiKey: string;
|
|
||||||
groqApiKey: string;
|
|
||||||
ollamaApiUrl: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SettingsDialog = ({
|
const SettingsDialog = ({
|
||||||
isOpen,
|
isOpen,
|
||||||
|
@ -21,7 +11,7 @@ const SettingsDialog = ({
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
setIsOpen: (isOpen: boolean) => void;
|
setIsOpen: (isOpen: boolean) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const [config, setConfig] = useState<SettingsType | null>(null);
|
const [config, setConfig] = useState<Settings | null>(null);
|
||||||
const [selectedChatModelProvider, setSelectedChatModelProvider] = useState<
|
const [selectedChatModelProvider, setSelectedChatModelProvider] = useState<
|
||||||
string | null
|
string | null
|
||||||
>(null);
|
>(null);
|
||||||
|
@ -42,13 +32,7 @@ const SettingsDialog = ({
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
const fetchConfig = async () => {
|
const fetchConfig = async () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/config`, {
|
const data = await getConfig();
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = (await res.json()) as SettingsType;
|
|
||||||
setConfig(data);
|
setConfig(data);
|
||||||
|
|
||||||
const chatModelProvidersKeys = Object.keys(
|
const chatModelProvidersKeys = Object.keys(
|
||||||
|
@ -66,30 +50,28 @@ const SettingsDialog = ({
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
const chatModelProvider =
|
const chatModelProvider =
|
||||||
localStorage.getItem('chatModelProvider') ||
|
(localStorage.getItem('chatModelProvider') ??
|
||||||
defaultChatModelProvider ||
|
defaultChatModelProvider) ||
|
||||||
'';
|
'';
|
||||||
const chatModel =
|
const chatModel =
|
||||||
localStorage.getItem('chatModel') ||
|
(localStorage.getItem('chatModel') ??
|
||||||
(data.chatModelProviders &&
|
data.chatModelProviders?.[chatModelProvider]?.[0]) ||
|
||||||
data.chatModelProviders[chatModelProvider]?.[0]) ||
|
|
||||||
'';
|
'';
|
||||||
const embeddingModelProvider =
|
const embeddingModelProvider =
|
||||||
localStorage.getItem('embeddingModelProvider') ||
|
(localStorage.getItem('embeddingModelProvider') ??
|
||||||
defaultEmbeddingModelProvider ||
|
defaultEmbeddingModelProvider) ||
|
||||||
'';
|
'';
|
||||||
const embeddingModel =
|
const embeddingModel =
|
||||||
localStorage.getItem('embeddingModel') ||
|
(localStorage.getItem('embeddingModel') ??
|
||||||
(data.embeddingModelProviders &&
|
data.embeddingModelProviders?.[embeddingModelProvider]?.[0]) ||
|
||||||
data.embeddingModelProviders[embeddingModelProvider]?.[0]) ||
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
setSelectedChatModelProvider(chatModelProvider);
|
setSelectedChatModelProvider(chatModelProvider);
|
||||||
setSelectedChatModel(chatModel);
|
setSelectedChatModel(chatModel);
|
||||||
setSelectedEmbeddingModelProvider(embeddingModelProvider);
|
setSelectedEmbeddingModelProvider(embeddingModelProvider);
|
||||||
setSelectedEmbeddingModel(embeddingModel);
|
setSelectedEmbeddingModel(embeddingModel);
|
||||||
setCustomOpenAIApiKey(localStorage.getItem('openAIApiKey') || '');
|
setCustomOpenAIApiKey(localStorage.getItem('openAIApiKey') ?? '');
|
||||||
setCustomOpenAIBaseURL(localStorage.getItem('openAIBaseURL') || '');
|
setCustomOpenAIBaseURL(localStorage.getItem('openAIBaseURL') ?? '');
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Message } from '@/components/ChatWindow';
|
import { Message } from '@/components/ChatWindow';
|
||||||
|
import { Settings } from '@/types/Settings';
|
||||||
|
|
||||||
export const getSuggestions = async (chatHisory: Message[]) => {
|
export const getSuggestions = async (chatHistory: Message[]) => {
|
||||||
const chatModel = localStorage.getItem('chatModel');
|
const chatModel = localStorage.getItem('chatModel');
|
||||||
const chatModelProvider = localStorage.getItem('chatModelProvider');
|
const chatModelProvider = localStorage.getItem('chatModelProvider');
|
||||||
|
|
||||||
|
@ -10,7 +11,7 @@ export const getSuggestions = async (chatHisory: Message[]) => {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
chat_history: chatHisory,
|
chat_history: chatHistory,
|
||||||
chat_model: chatModel,
|
chat_model: chatModel,
|
||||||
chat_model_provider: chatModelProvider,
|
chat_model_provider: chatModelProvider,
|
||||||
}),
|
}),
|
||||||
|
@ -20,3 +21,13 @@ export const getSuggestions = async (chatHisory: Message[]) => {
|
||||||
|
|
||||||
return data.suggestions;
|
return data.suggestions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export async function getConfig() {
|
||||||
|
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/config`, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (await res.json()) as Settings;
|
||||||
|
}
|
||||||
|
|
12
ui/types/Settings.ts
Normal file
12
ui/types/Settings.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
export interface Settings {
|
||||||
|
chatModelProviders: {
|
||||||
|
[key: string]: string[];
|
||||||
|
};
|
||||||
|
embeddingModelProviders: {
|
||||||
|
[key: string]: string[];
|
||||||
|
};
|
||||||
|
openaiApiKey: string;
|
||||||
|
groqApiKey: string;
|
||||||
|
ollamaApiUrl: string;
|
||||||
|
copilotEnabled: boolean;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue