Phase 004: remove the desktop shell, website tooling, and bundled hermes CLI

- Drop all desktop/Electron branches, scripts, and UI (title bar, pets,
  desktop bridge); LAN endpoint kind is now web/custom only
- Replace the bundled hermes CLI with user-side installation: add
  GET /api/hermes/cli-status plus a HermesMissingView onboarding guide
- Remove the version-management UI (snapshots handled by git) and prune
  dead website/mcu/claude scripts and lockfile entries
This commit is contained in:
2026-10-16 15:33:56 +08:00
parent 8c1ddf415f
commit 4701bf0ad0
49 changed files with 354 additions and 2403 deletions
+18 -24
View File
@@ -1,21 +1,22 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import { hasApiKey, isStoredSuperAdmin } from '@/api/client'
import { checkHermesCliAvailable } from '@/api/hermes/system'
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/desktop-pet',
name: 'desktop.pet',
component: () => import('@/views/hermes/DesktopPetView.vue'),
meta: { public: true },
},
{
path: '/',
name: 'login',
component: () => import('@/views/LoginView.vue'),
meta: { public: true },
},
{
path: '/hermes-missing',
name: 'hermes.missing',
component: () => import('@/views/hermes/HermesMissingView.vue'),
meta: { public: true },
},
{
path: '/hermes/chat',
name: 'hermes.chat',
@@ -169,29 +170,22 @@ const router = createRouter({
],
})
async function ensureDesktopAuth(): Promise<void> {
if (hasApiKey()) return
const bridge = (window as typeof window & {
hermesDesktop?: { isDesktop?: boolean; ensureAuth?: () => Promise<boolean> }
}).hermesDesktop
if (bridge?.isDesktop === true && bridge.ensureAuth) {
await bridge.ensureAuth().catch(() => false)
}
}
function isDesktopShell(): boolean {
return (window as typeof window & {
hermesDesktop?: { isDesktop?: boolean }
}).hermesDesktop?.isDesktop === true
}
router.beforeEach(async (to, _from, next) => {
await ensureDesktopAuth()
// hermes CLI missing guide: probe once per page load before anything else.
// checkHermesCliAvailable fails open, so only an explicit "missing" answer
// from the server sends the user to the guide page.
if (to.name !== 'hermes.missing') {
const cliAvailable = await checkHermesCliAvailable()
if (!cliAvailable) {
next({ name: 'hermes.missing' })
return
}
}
// Public pages don't need auth
if (to.meta.public) {
// Already has key, skip login
if (to.name === 'login' && hasApiKey() && !isDesktopShell()) {
if (to.name === 'login' && hasApiKey()) {
next({ path: '/hermes/chat' })
return
}