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:
@@ -5,20 +5,11 @@ interface CompletionNotificationPayload {
|
||||
tag?: string
|
||||
}
|
||||
|
||||
interface HermesDesktopBridge {
|
||||
isDesktop?: boolean
|
||||
notifyCompletion?: (payload: CompletionNotificationPayload) => Promise<boolean>
|
||||
}
|
||||
|
||||
export interface CompletionNotificationPermissionResult {
|
||||
granted: boolean
|
||||
reason?: 'unsupported' | 'insecure' | 'denied'
|
||||
}
|
||||
|
||||
type WindowWithHermesDesktop = Window & typeof globalThis & {
|
||||
hermesDesktop?: HermesDesktopBridge
|
||||
}
|
||||
|
||||
function withTimeout<T>(promise: Promise<T>, timeoutMs: number, fallback: T): Promise<T> {
|
||||
return new Promise<T>((resolve) => {
|
||||
const timer = window.setTimeout(() => resolve(fallback), timeoutMs)
|
||||
@@ -35,11 +26,6 @@ function withTimeout<T>(promise: Promise<T>, timeoutMs: number, fallback: T): Pr
|
||||
})
|
||||
}
|
||||
|
||||
function desktopBridge(): HermesDesktopBridge | undefined {
|
||||
if (typeof window === 'undefined') return undefined
|
||||
return (window as WindowWithHermesDesktop).hermesDesktop
|
||||
}
|
||||
|
||||
function supportsBrowserNotification(): boolean {
|
||||
return typeof window !== 'undefined' && 'Notification' in window
|
||||
}
|
||||
@@ -76,12 +62,7 @@ async function showServiceWorkerNotification(payload: CompletionNotificationPayl
|
||||
}
|
||||
}
|
||||
|
||||
export function isDesktopNotificationRuntime(): boolean {
|
||||
return desktopBridge()?.isDesktop === true
|
||||
}
|
||||
|
||||
export async function requestCompletionNotificationPermission(): Promise<CompletionNotificationPermissionResult> {
|
||||
if (isDesktopNotificationRuntime()) return { granted: true }
|
||||
if (!supportsBrowserNotification()) return { granted: false, reason: 'unsupported' }
|
||||
if (!isBrowserNotificationSecureContext()) return { granted: false, reason: 'insecure' }
|
||||
if (Notification.permission === 'granted') return { granted: true }
|
||||
@@ -102,16 +83,6 @@ export async function requestCompletionNotificationPermission(): Promise<Complet
|
||||
}
|
||||
|
||||
export async function showCompletionNotification(payload: CompletionNotificationPayload): Promise<boolean> {
|
||||
const bridge = desktopBridge()
|
||||
if (bridge?.isDesktop && bridge.notifyCompletion) {
|
||||
try {
|
||||
return await bridge.notifyCompletion(payload)
|
||||
} catch (err) {
|
||||
console.warn('Failed to show desktop completion notification:', err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if (!supportsBrowserNotification() || !isBrowserNotificationSecureContext() || Notification.permission !== 'granted') {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
export interface DesktopWindowBounds {
|
||||
x: number
|
||||
y: number
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
export interface DesktopPetWindowState {
|
||||
bounds: DesktopWindowBounds
|
||||
visible: boolean
|
||||
}
|
||||
|
||||
export interface HermesDesktopBridge {
|
||||
getToken: () => Promise<string>
|
||||
ensureAuth?: () => Promise<boolean>
|
||||
retryBootstrap: (source?: 'cf' | 'github') => Promise<void>
|
||||
notifyCompletion: (payload: { title: string; body?: string; icon?: string; tag?: string }) => Promise<boolean>
|
||||
getWindowState: () => Promise<{ isMaximized: boolean }>
|
||||
windowControl: (action: 'minimize' | 'toggle-maximize' | 'close') => Promise<{ isMaximized: boolean }>
|
||||
getPetWindowState?: () => Promise<DesktopPetWindowState>
|
||||
setPetWindowBounds?: (bounds: DesktopWindowBounds) => Promise<DesktopPetWindowState>
|
||||
setPetWindowVisible?: (visible: boolean) => Promise<DesktopPetWindowState>
|
||||
onPetWindowRefresh?: (callback: () => void) => () => void
|
||||
platform: string
|
||||
isDesktop: boolean
|
||||
windowKind?: 'main' | 'pet'
|
||||
}
|
||||
|
||||
export type WindowWithHermesDesktop = Window & typeof globalThis & {
|
||||
hermesDesktop?: HermesDesktopBridge
|
||||
}
|
||||
|
||||
export function desktopBridge(): HermesDesktopBridge | undefined {
|
||||
return (window as WindowWithHermesDesktop).hermesDesktop
|
||||
}
|
||||
|
||||
export function isDesktopShell(): boolean {
|
||||
return desktopBridge()?.isDesktop === true
|
||||
}
|
||||
|
||||
export function isDesktopPetWindow(): boolean {
|
||||
return desktopBridge()?.windowKind === 'pet'
|
||||
}
|
||||
Reference in New Issue
Block a user