feat: add model selector, skills/memory pages, and config management

- Add model selector in sidebar that discovers models from auth.json credential pool
- Add per-session model display (badge in chat header and session list)
- Add skills browser page and memory editor page
- Add BFF routes for skills, memory, and config model management
- Model switching updates config.yaml provider field to bypass env auto-detection
- Refactor Settings page, simplify ChatInput with file upload
- Add attachment upload support via BFF /upload endpoint

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
ekko
2026-04-12 23:23:50 +08:00
parent ee9f56dfbd
commit 5887462f7d
21 changed files with 1941 additions and 106 deletions
+29
View File
@@ -2,6 +2,7 @@
import { computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useAppStore } from '@/stores/app'
import ModelSelector from './ModelSelector.vue'
const route = useRoute()
const router = useRouter()
@@ -47,6 +48,32 @@ function handleNav(key: string) {
<span>Jobs</span>
</button>
<button
class="nav-item"
:class="{ active: selectedKey === 'skills' }"
@click="handleNav('skills')"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<polygon points="12 2 2 7 12 12 22 7 12 2" />
<polyline points="2 17 12 22 22 17" />
<polyline points="2 12 12 17 22 12" />
</svg>
<span>Skills</span>
</button>
<button
class="nav-item"
:class="{ active: selectedKey === 'memory' }"
@click="handleNav('memory')"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M9 18h6" />
<path d="M10 22h4" />
<path d="M12 2a7 7 0 0 0-4 12.7V17h8v-2.3A7 7 0 0 0 12 2z" />
</svg>
<span>Memory</span>
</button>
<button
class="nav-item"
:class="{ active: selectedKey === 'logs' }"
@@ -63,6 +90,8 @@ function handleNav(key: string) {
</button>
</nav>
<ModelSelector />
<div class="sidebar-footer">
<div class="status-row">
<div class="status-indicator" :class="{ connected: appStore.connected, disconnected: !appStore.connected }">