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:
2026-02-10 21:32:02 -05:00
parent 834fd80640
commit 38b1ac933e
20 changed files with 1257 additions and 236 deletions
+45
View File
@@ -1,11 +1,28 @@
<script setup lang="ts">
import { computed } from "vue";
import { useTheme } from "@/composables/useTheme";
import { useChatStore } from "@/stores/chat";
const { theme, toggleTheme } = useTheme();
const chatStore = useChatStore();
const emit = defineEmits<{
toggleChatPanel: [];
}>();
const statusLabel = computed(() => {
if (chatStore.ollamaStatus === "unavailable") return "Ollama unavailable";
if (chatStore.modelStatus === "not_found") return "Model downloading...";
if (chatStore.chatReady) return "Connected";
return "Checking...";
});
const statusClass = computed(() => {
if (chatStore.ollamaStatus === "unavailable") return "status-red";
if (chatStore.modelStatus === "not_found") return "status-yellow";
if (chatStore.chatReady) return "status-green";
return "status-yellow";
});
</script>
<template>
@@ -16,6 +33,10 @@ const emit = defineEmits<{
<router-link to="/notes" class="nav-link">Notes</router-link>
<router-link to="/tasks" class="nav-link">Tasks</router-link>
<router-link to="/chat" class="nav-link">Chat</router-link>
<router-link to="/settings" class="nav-link">Settings</router-link>
<span class="status-indicator" :class="statusClass" :title="statusLabel">
<span class="status-dot"></span>
</span>
<button class="btn-chat-panel" @click="emit('toggleChatPanel')" title="Open chat panel">
&#x1F4AC;
</button>
@@ -59,6 +80,30 @@ const emit = defineEmits<{
.nav-link:hover {
color: var(--color-primary);
}
.status-indicator {
display: flex;
align-items: center;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
}
.status-green .status-dot {
background: #22c55e;
}
.status-yellow .status-dot {
background: #eab308;
animation: pulse-dot 2s infinite;
}
.status-red .status-dot {
background: #ef4444;
}
@keyframes pulse-dot {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
.btn-chat-panel {
background: none;
border: 1px solid var(--color-border);