feat: add Node.js version warning, fix provider URL detection, and add v0.4.4 changelog (#146)

- Display persistent warning bar when Node.js version < 23
- Fix provider model fetching to support non-v1 API versions (e.g. /v4)
- Add v0.4.4 changelog entries to frontend
- Bump version to 0.4.4

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
ekko
2026-04-23 12:57:42 +08:00
committed by GitHub
parent 0cc31ee999
commit 1abe308742
16 changed files with 87 additions and 3 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "hermes-web-ui",
"version": "0.4.3",
"version": "0.4.4",
"description": "Self-hosted AI chat dashboard for Hermes Agent — multi-model (Claude, GPT, Gemini, DeepSeek) web UI with Telegram, Discord, Slack, WhatsApp integration",
"repository": {
"type": "git",
+27
View File
@@ -2,6 +2,7 @@
import { onMounted, onUnmounted, computed, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { darkTheme, NConfigProvider, NMessageProvider, NDialogProvider, NNotificationProvider } from 'naive-ui'
import { useI18n } from 'vue-i18n'
import { getThemeOverrides } from '@/styles/theme'
import { useTheme } from '@/composables/useTheme'
import AppSidebar from '@/components/layout/AppSidebar.vue'
@@ -10,6 +11,7 @@ import { useAppStore } from '@/stores/hermes/app'
import SessionSearchModal from '@/components/hermes/chat/SessionSearchModal.vue'
const { isDark } = useTheme()
const { t } = useI18n()
const appStore = useAppStore()
const route = useRoute()
const router = useRouter()
@@ -20,6 +22,12 @@ const naiveTheme = computed(() => isDark.value ? darkTheme : null)
const isLoginPage = computed(() => route.name === 'login')
const nodeVersionLow = computed(() => {
const v = appStore.nodeVersion
const major = parseInt(v.split('.')[0], 10)
return !isNaN(major) && major < 23
})
// Close mobile sidebar on route change
watch(() => route.path, () => {
appStore.closeSidebar()
@@ -49,6 +57,9 @@ useKeyboard()
<NMessageProvider>
<NDialogProvider>
<NNotificationProvider>
<div v-if="nodeVersionLow && ready" class="node-warning-bar">
{{ t('sidebar.nodeVersionWarning', { version: appStore.nodeVersion }) }}
</div>
<div v-if="ready" class="app-layout" :class="{ 'no-sidebar': isLoginPage }">
<button v-if="!isLoginPage" class="hamburger-btn" @click="appStore.toggleSidebar">
<img src="/logo.png" alt="Menu" style="width: 24px; height: 24px;" />
@@ -89,4 +100,20 @@ useKeyboard()
height: calc(100 * var(--vh));
}
}
.node-warning-bar {
position: absolute;
top: 0;
left: 0;
width: 100%;
z-index: 100;
padding: 4px 16px;
font-size: 12px;
font-weight: 500;
color: #b45309;
background-color: #fef3c7;
border-bottom: 1px solid #fde68a;
text-align: center;
line-height: 1.4;
}
</style>
+1
View File
@@ -6,6 +6,7 @@ export interface HealthResponse {
webui_version?: string
webui_latest?: string
webui_update_available?: boolean
node_version?: string
}
// Config-based model types
@@ -95,7 +95,7 @@ async function fetchModels() {
fetchingModels.value = true
try {
const base = base_url.replace(/\/+$/, '')
const url = base.endsWith('/v1') ? `${base}/models` : `${base}/v1/models`
const url = /\/v\d+\/?$/.test(base) ? `${base}/models` : `${base}/v1/models`
const headers: Record<string, string> = {}
if (formData.value.api_key.trim()) {
headers['Authorization'] = `Bearer ${formData.value.api_key.trim()}`
+5
View File
@@ -5,6 +5,11 @@ export interface ChangelogEntry {
}
export const changelog: ChangelogEntry[] = [
{
version: '0.4.4',
date: '2026-04-23',
changes: ['changelog.new_0_4_4_1', 'changelog.new_0_4_4_2', 'changelog.new_0_4_4_3', 'changelog.new_0_4_4_4', 'changelog.new_0_4_4_5'],
},
{
version: '0.4.3',
date: '2026-04-22',
+6
View File
@@ -84,6 +84,7 @@ export default {
updateSuccess: 'Aktualisierung abgeschlossen, bitte Server neu starten',
updateFailed: 'Aktualisierung fehlgeschlagen',
logout: 'Abmelden',
nodeVersionWarning: 'Node.js v{version} erkannt. Version 23+ wird fur volle Funktionalitat benotigt (SQLite, node-pty).',
changelog: 'Anderungsprotokoll',
noChangelog: 'Kein Anderungsprotokoll verfugbar',
},
@@ -510,6 +511,11 @@ export default {
// Anderungsprotokoll
changelog: {
new_0_4_4_1: 'Dateibrowser mit Multi-Backend-Unterstutzung hinzugefugt (local/Docker/SSH/Singularity)',
new_0_4_4_2: 'Dateidownload aus Chat-Nachrichtenanhangen hinzugefugt',
new_0_4_4_3: 'Live-Badge auf aktiven Chat-Sitzungen hinzugefugt',
new_0_4_4_4: 'StepFun- und Nous-Portal-Provider-Unterstutzung hinzugefugt',
new_0_4_4_5: 'Spezialzeichen-Suche verursacht 500-Fehler behoben',
new_0_4_3_1: 'Benutzername/Passwort-Login neben Token-Authentifizierung hinzugefugt',
new_0_4_3_2: 'Kontoeinstellungen fur Anmeldeinformationen hinzugefugt',
new_0_4_3_3: 'Abmelden-Schaltflache in der Seitenleiste hinzugefugt',
+5
View File
@@ -612,6 +612,11 @@ export default {
// Changelog
changelog: {
new_0_4_4_1: 'Add file browser with multi-backend support (local/Docker/SSH/Singularity)',
new_0_4_4_2: 'Add file download from chat message attachments',
new_0_4_4_3: 'Add live badge on active chat sessions',
new_0_4_4_4: 'Add StepFun and Nous Portal provider support',
new_0_4_4_5: 'Fix special character search queries causing 500 error',
new_0_4_3_1: 'Add username/password login alongside token authentication',
new_0_4_3_2: 'Add account settings for managing credentials (setup, change password, change username)',
new_0_4_3_3: 'Add logout button to sidebar',
+6
View File
@@ -84,6 +84,7 @@ export default {
updateSuccess: 'Actualizacion completa, por favor reinicia el servidor',
updateFailed: 'Error al actualizar',
logout: 'Cerrar sesion',
nodeVersionWarning: 'Node.js v{version} detectado. Se requiere la version 23+ para todas las funcionalidades (SQLite, node-pty).',
changelog: 'Registro de cambios',
noChangelog: 'No hay registro de cambios',
},
@@ -510,6 +511,11 @@ export default {
// Registro de cambios
changelog: {
new_0_4_4_1: 'Agregar explorador de archivos con soporte multi-backend (local/Docker/SSH/Singularity)',
new_0_4_4_2: 'Agregar descarga de archivos desde archivos adjuntos del chat',
new_0_4_4_3: 'Agregar indicador en vivo en sesiones de chat activas',
new_0_4_4_4: 'Agregar soporte para proveedores StepFun y Nous Portal',
new_0_4_4_5: 'Corregir error 500 al buscar con caracteres especiales',
new_0_4_3_1: 'Agregar inicio de sesion con usuario/contrasena junto a autenticacion por token',
new_0_4_3_2: 'Agregar configuracion de cuenta para gestionar credenciales',
new_0_4_3_3: 'Agregar boton de cerrar sesion en la barra lateral',
+6
View File
@@ -84,6 +84,7 @@ export default {
updateSuccess: 'Mise a jour terminee, veuillez redemarrer le serveur',
updateFailed: 'Echec de la mise a jour',
logout: 'Deconnexion',
nodeVersionWarning: 'Node.js v{version} detecte. La version 23+ est requise pour toutes les fonctionnalites (SQLite, node-pty).',
changelog: 'Journal des modifications',
noChangelog: 'Aucun journal disponible',
},
@@ -510,6 +511,11 @@ export default {
// Journal des modifications
changelog: {
new_0_4_4_1: 'Ajout du navigateur de fichiers avec support multi-backend (local/Docker/SSH/Singularity)',
new_0_4_4_2: 'Ajout du telechargement de fichiers depuis les pieces jointes',
new_0_4_4_3: 'Ajout du badge en direct sur les sessions actives',
new_0_4_4_4: 'Ajout du support des fournisseurs StepFun et Nous Portal',
new_0_4_4_5: 'Correction de l\'erreur 500 lors de la recherche avec caracteres speciaux',
new_0_4_3_1: 'Ajouter la connexion par nom d\'utilisateur/mot de passe en plus du token',
new_0_4_3_2: 'Ajouter les parametres de compte pour gerer les identifiants',
new_0_4_3_3: 'Ajouter le bouton de deconnexion dans la barre laterale',
+6
View File
@@ -84,6 +84,7 @@ export default {
updateSuccess: '更新が完了しました。サーバーを再起動してください',
updateFailed: '更新に失敗しました',
logout: 'ログアウト',
nodeVersionWarning: 'Node.js v{version} が検出されました。全機能にはバージョン23+が必要です(SQLite、node-pty)。',
changelog: '更新履歴',
noChangelog: '更新履歴はありません',
},
@@ -510,6 +511,11 @@ export default {
// 更新履歴
changelog: {
new_0_4_4_1: 'ファイルブラウザを追加(local/Docker/SSH/Singularity対応)',
new_0_4_4_2: 'チャットメッセージの添付ファイルダウンロードを追加',
new_0_4_4_3: 'アクティブセッションにライブバッジを表示',
new_0_4_4_4: 'StepFunとNous Portalプロバイダーに対応',
new_0_4_4_5: '特殊文字検索で500エラーになる問題を修正',
new_0_4_3_1: 'トークン認証に加えてユーザー名/パスワードログインを追加',
new_0_4_3_2: '資格情報管理のためのアカウント設定を追加',
new_0_4_3_3: 'サイドバーにログアウトボタンを追加',
+6
View File
@@ -84,6 +84,7 @@ export default {
updateSuccess: '업데이트 완료, 서버를 재시작해 주세요',
updateFailed: '업데이트 실패',
logout: '로그아웃',
nodeVersionWarning: 'Node.js v{version}이(가) 감지되었습니다. 전체 기능에는 버전 23+가 필요합니다(SQLite, node-pty).',
changelog: '변경 이력',
noChangelog: '변경 이력이 없습니다',
},
@@ -510,6 +511,11 @@ export default {
// 변경 이력
changelog: {
new_0_4_4_1: '파일 브라우저 추가 (local/Docker/SSH/Singularity 지원)',
new_0_4_4_2: '채팅 메시지 첨부 파일 다운로드 추가',
new_0_4_4_3: '활성 세션에 라이브 배지 표시',
new_0_4_4_4: 'StepFun 및 Nous Portal 프로바이더 지원 추가',
new_0_4_4_5: '특수문자 검색 시 500 에러 수정',
new_0_4_3_1: '토큰 인증과 함께 사용자 이름/비밀번호 로그인 추가',
new_0_4_3_2: '자격 증명 관리를 위한 계정 설정 추가',
new_0_4_3_3: '사이드바에 로그아웃 버튼 추가',
+6
View File
@@ -84,6 +84,7 @@ export default {
updateSuccess: 'Atualizacao concluida, por favor reinicie o servidor',
updateFailed: 'Falha na atualizacao',
logout: 'Sair',
nodeVersionWarning: 'Node.js v{version} detectado. A versao 23+ e necessaria para todas as funcionalidades (SQLite, node-pty).',
changelog: 'Registro de alteracoes',
noChangelog: 'Nenhum registro disponivel',
},
@@ -510,6 +511,11 @@ export default {
// Registro de alteracoes
changelog: {
new_0_4_4_1: 'Adicionar navegador de arquivos com suporte multi-backend (local/Docker/SSH/Singularity)',
new_0_4_4_2: 'Adicionar download de arquivos dos anexos de chat',
new_0_4_4_3: 'Adicionar indicador ao vivo nas sessoes de chat ativas',
new_0_4_4_4: 'Adicionar suporte para provedores StepFun e Nous Portal',
new_0_4_4_5: 'Corrigir erro 500 ao pesquisar com caracteres especiais',
new_0_4_3_1: 'Adicionar login por usuario/senha junto com autenticacao por token',
new_0_4_3_2: 'Adicionar configuracoes de conta para gerenciar credenciais',
new_0_4_3_3: 'Adicionar botao de sair na barra lateral',
+6
View File
@@ -97,6 +97,7 @@ export default {
updateSuccess: '更新完成,请重启服务',
updateFailed: '更新失败',
logout: '退出登录',
nodeVersionWarning: '检测到 Node.js v{version},请升级到23以上版本。',
changelog: '更新日志',
noChangelog: '暂无更新日志',
},
@@ -614,6 +615,11 @@ export default {
// 更新日志
changelog: {
new_0_4_4_1: '新增文件浏览器,支持多后端(本地/Docker/SSH/Singularity',
new_0_4_4_2: '新增聊天消息附件文件下载',
new_0_4_4_3: '活跃会话显示实时状态标签',
new_0_4_4_4: '新增 StepFun 和 Nous Portal Provider 支持',
new_0_4_4_5: '修复特殊字符搜索导致 500 错误',
new_0_4_3_1: '新增用户名/密码登录,支持与令牌认证并存',
new_0_4_3_2: '新增账户设置:配置密码、修改密码、修改用户名',
new_0_4_3_3: '侧边栏新增退出登录按钮',
+3
View File
@@ -20,6 +20,7 @@ export const useAppStore = defineStore('app', () => {
const selectedModel = ref('')
const selectedProvider = ref('')
const healthPollTimer = ref<ReturnType<typeof setInterval>>()
const nodeVersion = ref('')
// Settings
const streamEnabled = ref(true)
@@ -47,6 +48,7 @@ export const useAppStore = defineStore('app', () => {
if (res.webui_version) serverVersion.value = res.webui_version
if (res.webui_latest) latestVersion.value = res.webui_latest
updateAvailable.value = !!res.webui_update_available
if (res.node_version) nodeVersion.value = res.node_version
} catch {
connected.value = false
}
@@ -115,6 +117,7 @@ export const useAppStore = defineStore('app', () => {
connected,
serverVersion,
latestVersion,
nodeVersion,
updateAvailable,
updating,
doUpdate,
@@ -48,6 +48,7 @@ export async function healthCheck(ctx: any) {
webui_version: LOCAL_VERSION,
webui_latest: cachedLatestVersion,
webui_update_available: cachedLatestVersion && cachedLatestVersion !== LOCAL_VERSION,
node_version: process.versions.node,
}
}
@@ -182,7 +182,7 @@ export async function listFilesRecursive(dir: string, prefix: string): Promise<{
export async function fetchProviderModels(baseUrl: string, apiKey: string): Promise<string[]> {
const base = baseUrl.replace(/\/+$/, '')
const modelsUrl = base.endsWith('/v1') ? `${base}/models` : `${base}/v1/models`
const modelsUrl = /\/v\d+\/?$/.test(base) ? `${base}/models` : `${base}/v1/models`
try {
const res = await fetch(modelsUrl, {
headers: { Authorization: `Bearer ${apiKey}` },