Add settings page, model management, and chat UX improvements
- Settings infrastructure: key-value settings table, GET/PUT API, Pinia store - Configurable assistant name (default "Fable") in settings and LLM system prompt - Model catalog with 18 models in 3 categories (General Purpose, Coding, Uncensored / Creative Writing) with download/select/remove functionality - Move Ollama status indicator from chat views to global nav bar - Chat bubble layout: user messages right-aligned, assistant left-aligned - Floating dark input bar with auto-focus and circular send button - Fix HTML entity rendering (' apostrophe issue in marked/DOMPurify pipeline) - Fix new chat button navigation (fetchConversation before router.push) - Recent chats section on home page with "New Chat" button - Update summary.md with Phase 4.5 changes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import { ref, computed } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
import { apiGet, apiPut, apiPost } from "@/api/client";
|
||||
import type { AppSettings } from "@/types/settings";
|
||||
|
||||
export const useSettingsStore = defineStore("settings", () => {
|
||||
const settings = ref<AppSettings>({});
|
||||
const loading = ref(false);
|
||||
const installedModels = ref<string[]>([]);
|
||||
|
||||
const assistantName = computed(
|
||||
() => settings.value.assistant_name || "Fable"
|
||||
);
|
||||
|
||||
const defaultModel = computed(
|
||||
() => settings.value.default_model || ""
|
||||
);
|
||||
|
||||
async function fetchSettings() {
|
||||
loading.value = true;
|
||||
try {
|
||||
settings.value = await apiGet<AppSettings>("/api/settings");
|
||||
} catch {
|
||||
// Use defaults on error
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function updateSettings(updates: AppSettings) {
|
||||
loading.value = true;
|
||||
try {
|
||||
settings.value = await apiPut<AppSettings>("/api/settings", updates);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchInstalledModels() {
|
||||
try {
|
||||
const data = await apiGet<{ models: { name: string }[] }>("/api/chat/models");
|
||||
installedModels.value = data.models.map((m) => m.name);
|
||||
} catch {
|
||||
installedModels.value = [];
|
||||
}
|
||||
}
|
||||
|
||||
async function pullModel(model: string) {
|
||||
await apiPost("/api/chat/models/pull", { model });
|
||||
}
|
||||
|
||||
async function deleteModel(model: string) {
|
||||
await apiPost("/api/chat/models/delete", { model });
|
||||
await fetchInstalledModels();
|
||||
}
|
||||
|
||||
return {
|
||||
settings,
|
||||
loading,
|
||||
installedModels,
|
||||
assistantName,
|
||||
defaultModel,
|
||||
fetchSettings,
|
||||
updateSettings,
|
||||
fetchInstalledModels,
|
||||
pullModel,
|
||||
deleteModel,
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user