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
+11 -11
View File
@@ -1,14 +1,19 @@
// @vitest-environment jsdom
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { beforeEach, describe, expect, it, vi } from 'vitest'
const mockHasApiKey = vi.hoisted(() => vi.fn())
const mockIsStoredSuperAdmin = vi.hoisted(() => vi.fn())
const mockCheckHermesCliAvailable = vi.hoisted(() => vi.fn())
vi.mock('@/api/client', () => ({
hasApiKey: mockHasApiKey,
isStoredSuperAdmin: mockIsStoredSuperAdmin,
}))
vi.mock('@/api/hermes/system', () => ({
checkHermesCliAvailable: mockCheckHermesCliAvailable,
}))
async function loadRouter() {
vi.resetModules()
return (await import('@/router')).default
@@ -18,17 +23,13 @@ describe('router login redirect', () => {
beforeEach(() => {
mockHasApiKey.mockReturnValue(false)
mockIsStoredSuperAdmin.mockReturnValue(true)
mockCheckHermesCliAvailable.mockResolvedValue(true)
if (!document.queryCommandSupported) {
document.queryCommandSupported = vi.fn(() => false)
}
delete (window as any).hermesDesktop
window.location.hash = ''
})
afterEach(() => {
delete (window as any).hermesDesktop
})
it('keeps the web login redirect when a token exists', async () => {
mockHasApiKey.mockReturnValue(true)
const router = await loadRouter()
@@ -39,14 +40,13 @@ describe('router login redirect', () => {
expect(router.currentRoute.value.name).toBe('hermes.chat')
}, 60_000)
it('does not redirect desktop login when a stale token exists', async () => {
mockHasApiKey.mockReturnValue(true)
;(window as any).hermesDesktop = { isDesktop: true }
it('redirects to the hermes CLI guide when the CLI is missing', async () => {
mockCheckHermesCliAvailable.mockResolvedValue(false)
const router = await loadRouter()
await router.push('/')
await router.push('/hermes/chat')
await router.isReady()
expect(router.currentRoute.value.name).toBe('login')
expect(router.currentRoute.value.name).toBe('hermes.missing')
})
})