Files
Hermes-ui/packages/client/src/router/index.ts
T
ekko 4b6de351bd feat: add multi-gateway management with auto port detection
- Add GatewayManager for multi-profile gateway lifecycle management
- Auto-detect running gateways on startup via PID + health check
- Port conflict detection: check managed gateways, allocated ports, and
  system-level port availability (TCP bind test)
- Two-phase startup: sequential port resolution, parallel process launch
- Use `gateway start/restart` on normal systems, `gateway run --replace`
  on WSL/Docker
- Wait for health check before returning start/stop responses
- Add Gateways page with card-based layout showing profile status
- Reorganize sidebar navigation into collapsible groups
- Hide API server settings (now auto-managed by GatewayManager)
- Profile switch reloads page; Ctrl+C no longer stops gateways
- Remove redundant ensureApiServerConfig from index.ts and profiles.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 13:07:12 +08:00

98 lines
2.3 KiB
TypeScript

import { createRouter, createWebHashHistory } from 'vue-router'
import { hasApiKey } from '@/api/client'
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/',
name: 'login',
component: () => import('@/views/LoginView.vue'),
meta: { public: true },
},
{
path: '/hermes/chat',
name: 'hermes.chat',
component: () => import('@/views/hermes/ChatView.vue'),
},
{
path: '/hermes/jobs',
name: 'hermes.jobs',
component: () => import('@/views/hermes/JobsView.vue'),
},
{
path: '/hermes/models',
name: 'hermes.models',
component: () => import('@/views/hermes/ModelsView.vue'),
},
{
path: '/hermes/profiles',
name: 'hermes.profiles',
component: () => import('@/views/hermes/ProfilesView.vue'),
},
{
path: '/hermes/logs',
name: 'hermes.logs',
component: () => import('@/views/hermes/LogsView.vue'),
},
{
path: '/hermes/usage',
name: 'hermes.usage',
component: () => import('@/views/hermes/UsageView.vue'),
},
{
path: '/hermes/skills',
name: 'hermes.skills',
component: () => import('@/views/hermes/SkillsView.vue'),
},
{
path: '/hermes/memory',
name: 'hermes.memory',
component: () => import('@/views/hermes/MemoryView.vue'),
},
{
path: '/hermes/settings',
name: 'hermes.settings',
component: () => import('@/views/hermes/SettingsView.vue'),
},
{
path: '/hermes/gateways',
name: 'hermes.gateways',
component: () => import('@/views/hermes/GatewaysView.vue'),
},
{
path: '/hermes/channels',
name: 'hermes.channels',
component: () => import('@/views/hermes/ChannelsView.vue'),
},
{
path: '/hermes/terminal',
name: 'hermes.terminal',
component: () => import('@/views/hermes/TerminalView.vue'),
},
],
})
router.beforeEach((to, _from, next) => {
// Public pages don't need auth
if (to.meta.public) {
// Already has key, skip login
if (to.name === 'login' && hasApiKey()) {
next({ path: '/hermes/chat' })
return
}
next()
return
}
// All other pages require token
if (!hasApiKey()) {
next({ name: 'login' })
return
}
next()
})
export default router