Files
OllaHub/store/settings-store.ts
T
Evandro Fonseca Junior 8834ef2b4f feat: update dependencies and enhance chat functionality
- Added new Radix UI components including checkbox, label, popover, slider, switch, and tooltip to improve UI interactions.
- Integrated react-syntax-highlighter for better code rendering in chat messages.
- Updated package.json and pnpm-lock.yaml to include new dependencies and ensure compatibility.
- Enhanced chat input to support web search toggling, improving user experience during message composition.
- Implemented auto-saving of chat sessions and improved session management features.
- Refactored chat message rendering to clean up metadata and improve display quality.
2025-11-20 04:26:35 -03:00

243 lines
6.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
export interface SearchCategory {
id: string;
name: string;
baseSites: string[];
enabled: boolean;
}
export interface SettingsState {
// AI & Models
ollamaUrl: string;
selectedModel: string;
systemPrompt: string;
contextWindow: number;
// Web Search
webSearch: {
enabled: boolean;
maxResults: number;
timeout: number;
excludedDomains: string[];
maxConcurrentTabs: number;
totalSourcesLimit: number;
categories: SearchCategory[];
userCustomSites: string[];
};
// Actions
setOllamaUrl: (url: string) => void;
setSelectedModel: (model: string) => void;
setSystemPrompt: (prompt: string) => void;
setContextWindow: (ctx: number) => void;
setWebSearchEnabled: (enabled: boolean) => void;
setWebSearchMaxResults: (max: number) => void;
setWebSearchTimeout: (timeout: number) => void;
setWebSearchMaxConcurrentTabs: (max: number) => void;
setWebSearchTotalSourcesLimit: (limit: number) => void;
addExcludedDomain: (domain: string) => void;
removeExcludedDomain: (domain: string) => void;
toggleCategory: (categoryId: string) => void;
updateCategory: (category: SearchCategory) => void;
addCustomSite: (site: string) => void;
removeCustomSite: (site: string) => void;
resetSettings: () => void;
}
const defaultSystemPrompt = `Você é um assistente de IA local integrado ao OllaHub.
## REGRAS ABSOLUTAS
1. **Nunca** escreva tags \`<metadata>\`, JSON oculto ou textos como "Metadados:". Toda resposta deve ser apenas texto visível ao usuário.
2. Use Markdown limpo: títulos, listas e blocos de código com linguagem indicada.
3. Seja direto, técnico e objetivo. Resumos iniciais são bem-vindos em respostas longas.
4. Comandos e códigos devem estar em blocos triplos (\`\`\`bash, \`\`\`json, etc.).
5. Se receber um bloco [CONTEXTO WEB], use essas informações prioritariamente para responder.
## CONTEXTO WEB
- Quando informações da web forem fornecidas, use-as como fonte principal.
- Cite as fontes usando [1], [2], [3] ao final das frases quando usar informações do contexto web.
- Se o contexto não for suficiente, diga isso claramente.
## FORMATO SUGERIDO
- Resumo inicial (1–2 frases) quando necessário.
- Seções \`##\` para organizar o conteúdo.
- Listas para passos/itens.
- Blocos de código com linguagem específica.
## ESTILO
- Cite limitações, hipóteses e próximos passos.
- Inclua links apenas quando essencial.
- Respostas sempre limpas, sem metadados ou conteúdo oculto.`;
// Categorias padrão curadas
const defaultCategories: SearchCategory[] = [
{
id: 'academic',
name: 'Acadêmico',
baseSites: [
'scielo.br',
'arxiv.org',
'scholar.google.com',
'pubmed.ncbi.nlm.nih.gov',
'researchgate.net',
],
enabled: false,
},
{
id: 'news',
name: 'Notícias',
baseSites: [
'g1.globo.com',
'bbc.com',
'cnnbrasil.com.br',
'folha.uol.com.br',
'estadao.com.br',
],
enabled: true,
},
{
id: 'tech',
name: 'Tech & Dev',
baseSites: [
'github.com',
'stackoverflow.com',
'dev.to',
'tabnews.com.br',
'medium.com',
],
enabled: true,
},
{
id: 'finance',
name: 'Financeiro',
baseSites: [
'infomoney.com.br',
'bloomberg.com',
'valor.globo.com',
'investing.com',
'yahoo.com/finance',
],
enabled: false,
},
];
const initialState = {
ollamaUrl: 'http://localhost:11434',
selectedModel: '',
systemPrompt: defaultSystemPrompt,
contextWindow: 4096,
webSearch: {
enabled: true,
maxResults: 5,
timeout: 10,
excludedDomains: ['youtube.com', 'linkedin.com'],
maxConcurrentTabs: 5,
totalSourcesLimit: 40,
categories: defaultCategories,
userCustomSites: [],
},
};
export const useSettingsStore = create<SettingsState>()(
persist(
(set) => ({
...initialState,
setOllamaUrl: (url) => set({ ollamaUrl: url }),
setSelectedModel: (model) => set({ selectedModel: model }),
setSystemPrompt: (prompt) => set({ systemPrompt: prompt }),
setContextWindow: (ctx) => set({ contextWindow: ctx }),
setWebSearchEnabled: (enabled) =>
set((state) => ({
webSearch: { ...state.webSearch, enabled },
})),
setWebSearchMaxResults: (max) =>
set((state) => ({
webSearch: { ...state.webSearch, maxResults: max },
})),
setWebSearchTimeout: (timeout) =>
set((state) => ({
webSearch: { ...state.webSearch, timeout },
})),
setWebSearchMaxConcurrentTabs: (max) =>
set((state) => ({
webSearch: { ...state.webSearch, maxConcurrentTabs: max },
})),
setWebSearchTotalSourcesLimit: (limit) =>
set((state) => ({
webSearch: { ...state.webSearch, totalSourcesLimit: limit },
})),
addExcludedDomain: (domain) =>
set((state) => {
const normalized = domain.toLowerCase().trim().replace(/^https?:\/\//, '').replace(/\/$/, '');
if (!normalized || state.webSearch.excludedDomains.includes(normalized)) {
return state;
}
return {
webSearch: {
...state.webSearch,
excludedDomains: [...state.webSearch.excludedDomains, normalized],
},
};
}),
removeExcludedDomain: (domain) =>
set((state) => ({
webSearch: {
...state.webSearch,
excludedDomains: state.webSearch.excludedDomains.filter((d) => d !== domain),
},
})),
toggleCategory: (categoryId) =>
set((state) => ({
webSearch: {
...state.webSearch,
categories: state.webSearch.categories.map((cat) =>
cat.id === categoryId ? { ...cat, enabled: !cat.enabled } : cat
),
},
})),
updateCategory: (category) =>
set((state) => ({
webSearch: {
...state.webSearch,
categories: state.webSearch.categories.map((cat) =>
cat.id === category.id ? category : cat
),
},
})),
addCustomSite: (site) =>
set((state) => {
const normalized = site.toLowerCase().trim().replace(/^https?:\/\//, '').replace(/\/$/, '');
if (!normalized || state.webSearch.userCustomSites.includes(normalized)) {
return state;
}
return {
webSearch: {
...state.webSearch,
userCustomSites: [...state.webSearch.userCustomSites, normalized],
},
};
}),
removeCustomSite: (site) =>
set((state) => ({
webSearch: {
...state.webSearch,
userCustomSites: state.webSearch.userCustomSites.filter((s) => s !== site),
},
})),
resetSettings: () => set(initialState),
}),
{
name: 'ollahub-settings',
version: 1,
}
)
);