mirror of
https://github.com/EKKOLearnAI/hermes-web-ui.git
synced 2026-05-25 13:30:14 +00:00
feat: add gateway auto-start on boot and real health detection
- Auto-detect gateway connectivity on server startup, start gateway if not running - Fix /health endpoint to actually check gateway reachability instead of just CLI version - Fix MiniMax CN base_url from /anthropic to /v1 - Frontend connection status now reflects real gateway state Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+46
-4
@@ -15,12 +15,13 @@ import { fsRoutes } from './routes/filesystem'
|
||||
import { configRoutes } from './routes/config'
|
||||
import { weixinRoutes } from './routes/weixin'
|
||||
import * as hermesCli from './services/hermes-cli'
|
||||
const { restartGateway } = hermesCli
|
||||
const { restartGateway, startGateway, getVersion } = hermesCli
|
||||
|
||||
export async function bootstrap() {
|
||||
await mkdir(config.uploadDir, { recursive: true })
|
||||
await mkdir(config.dataDir, { recursive: true })
|
||||
await ensureApiServerConfig()
|
||||
await ensureGatewayRunning()
|
||||
|
||||
const app = new Koa()
|
||||
|
||||
@@ -35,12 +36,26 @@ export async function bootstrap() {
|
||||
app.use(configRoutes.routes())
|
||||
app.use(weixinRoutes.routes())
|
||||
|
||||
// Health endpoint with version
|
||||
// Health endpoint: check CLI version + gateway connectivity
|
||||
app.use(async (ctx, next) => {
|
||||
if (ctx.path === '/health') {
|
||||
const raw = await hermesCli.getVersion()
|
||||
const raw = await getVersion()
|
||||
const version = raw.split('\n')[0].replace('Hermes Agent ', '') || ''
|
||||
ctx.body = { status: 'ok', platform: 'hermes-agent', version }
|
||||
|
||||
let gatewayOk = false
|
||||
try {
|
||||
const res = await fetch(`${config.upstream.replace(/\/$/, '')}/health`, {
|
||||
signal: AbortSignal.timeout(5000),
|
||||
})
|
||||
gatewayOk = res.ok
|
||||
} catch { /* not reachable */ }
|
||||
|
||||
ctx.body = {
|
||||
status: gatewayOk ? 'ok' : 'error',
|
||||
platform: 'hermes-agent',
|
||||
version,
|
||||
gateway: gatewayOk ? 'running' : 'stopped',
|
||||
}
|
||||
return
|
||||
}
|
||||
await next()
|
||||
@@ -136,4 +151,31 @@ async function ensureApiServerConfig() {
|
||||
}
|
||||
}
|
||||
|
||||
async function ensureGatewayRunning() {
|
||||
const upstream = config.upstream.replace(/\/$/, '')
|
||||
try {
|
||||
const res = await fetch(`${upstream}/health`, { signal: AbortSignal.timeout(5000) })
|
||||
if (res.ok) {
|
||||
console.log(' ✓ Gateway is running')
|
||||
return
|
||||
}
|
||||
} catch {
|
||||
// Gateway not reachable
|
||||
}
|
||||
|
||||
console.log(' ⚠ Gateway not reachable, starting...')
|
||||
try {
|
||||
await startGateway()
|
||||
await new Promise(r => setTimeout(r, 3000))
|
||||
const res = await fetch(`${upstream}/health`, { signal: AbortSignal.timeout(5000) })
|
||||
if (res.ok) {
|
||||
console.log(' ✓ Gateway started successfully')
|
||||
return
|
||||
}
|
||||
console.log(' ✗ Gateway start attempted but still not reachable')
|
||||
} catch (err: any) {
|
||||
console.error(' ✗ Failed to start gateway:', err.message)
|
||||
}
|
||||
}
|
||||
|
||||
bootstrap()
|
||||
|
||||
@@ -182,7 +182,17 @@ export async function getVersion(): Promise<string> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Hermes Agent
|
||||
* Start Hermes gateway
|
||||
*/
|
||||
export async function startGateway(): Promise<string> {
|
||||
const { stdout, stderr } = await execFileAsync('hermes', ['gateway', 'start'], {
|
||||
timeout: 30000,
|
||||
})
|
||||
return stdout || stderr
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart Hermes gateway
|
||||
*/
|
||||
export async function restartGateway(): Promise<string> {
|
||||
const { stdout, stderr } = await execFileAsync('hermes', ['gateway', 'restart'], {
|
||||
|
||||
@@ -97,7 +97,7 @@ export const PROVIDER_PRESETS: ProviderPreset[] = [
|
||||
{
|
||||
label: 'MiniMax (China)',
|
||||
value: 'minimax-cn',
|
||||
base_url: 'https://api.minimaxi.com/anthropic',
|
||||
base_url: 'https://api.minimaxi.com/v1',
|
||||
models: ['MiniMax-M2.7', 'MiniMax-M2.5', 'MiniMax-M2.1', 'MiniMax-M2'],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -97,7 +97,7 @@ export const PROVIDER_PRESETS: ProviderPreset[] = [
|
||||
{
|
||||
label: 'MiniMax (China)',
|
||||
value: 'minimax-cn',
|
||||
base_url: 'https://api.minimaxi.com/anthropic',
|
||||
base_url: 'https://api.minimaxi.com/v1',
|
||||
models: ['MiniMax-M2.7', 'MiniMax-M2.5', 'MiniMax-M2.1', 'MiniMax-M2'],
|
||||
},
|
||||
{
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ export const useAppStore = defineStore('app', () => {
|
||||
async function checkConnection() {
|
||||
try {
|
||||
const res = await checkHealth()
|
||||
connected.value = true
|
||||
connected.value = res.status === 'ok'
|
||||
if (res.version) serverVersion.value = res.version
|
||||
} catch {
|
||||
connected.value = false
|
||||
|
||||
Reference in New Issue
Block a user