refactor: restructure project for multi-agent extensibility
- Migrate source to packages/client and packages/server directories - Namespace all Hermes-specific code under hermes/ subdirectories (api/hermes/, components/hermes/, views/hermes/, stores/hermes/) - Add hermes.* route names and /hermes/* path prefixes - Upgrade @koa/router to v15, adapt path-to-regexp v8 syntax - Fix proxy path rewriting: /api/hermes/v1/* → /v1/*, /api/hermes/* → /api/* - Fix frontend API paths to match backend /api/hermes/* routes - Fix WebSocket terminal path to /api/hermes/terminal - Add proxyMiddleware for reliable unmatched route proxying - Add profiles route module and hermes-cli profile commands - Update CLAUDE.md development guide with new architecture - Add Chinese README (README_zh.md) - Add Web Terminal feature to README Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, computed, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { NConfigProvider, NMessageProvider, NDialogProvider, NNotificationProvider } from 'naive-ui'
|
||||
import { themeOverrides } from '@/styles/theme'
|
||||
import AppSidebar from '@/components/layout/AppSidebar.vue'
|
||||
import { useKeyboard } from '@/composables/useKeyboard'
|
||||
import { useAppStore } from '@/stores/hermes/app'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const ready = ref(false)
|
||||
|
||||
const isLoginPage = computed(() => route.name === 'login')
|
||||
|
||||
// Close mobile sidebar on route change
|
||||
watch(() => route.path, () => {
|
||||
appStore.closeSidebar()
|
||||
})
|
||||
|
||||
// Wait for router to resolve before rendering layout
|
||||
router.isReady().then(() => {
|
||||
ready.value = true
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (!isLoginPage.value) {
|
||||
appStore.loadModels()
|
||||
appStore.startHealthPolling()
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
appStore.stopHealthPolling()
|
||||
})
|
||||
|
||||
useKeyboard()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NConfigProvider :theme-overrides="themeOverrides">
|
||||
<NMessageProvider>
|
||||
<NDialogProvider>
|
||||
<NNotificationProvider>
|
||||
<div v-if="ready" class="app-layout" :class="{ 'no-sidebar': isLoginPage }">
|
||||
<button v-if="!isLoginPage" class="hamburger-btn" @click="appStore.toggleSidebar">
|
||||
<img src="/logo.png" alt="Menu" style="width: 24px; height: 24px;" />
|
||||
</button>
|
||||
<div v-if="!isLoginPage && appStore.sidebarOpen" class="mobile-backdrop" @click="appStore.closeSidebar" />
|
||||
<AppSidebar v-if="!isLoginPage" />
|
||||
<main class="app-main">
|
||||
<router-view />
|
||||
</main>
|
||||
</div>
|
||||
</NNotificationProvider>
|
||||
</NDialogProvider>
|
||||
</NMessageProvider>
|
||||
</NConfigProvider>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use '@/styles/variables' as *;
|
||||
|
||||
.app-layout {
|
||||
display: flex;
|
||||
height: calc(100 * var(--vh));
|
||||
width: 100vw;
|
||||
overflow: hidden;
|
||||
|
||||
&.no-sidebar {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.app-main {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
background-color: $bg-primary;
|
||||
|
||||
.no-sidebar & {
|
||||
height: calc(100 * var(--vh));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user