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:
+1
-1
@@ -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",
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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: 'サイドバーにログアウトボタンを追加',
|
||||
|
||||
@@ -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: '사이드바에 로그아웃 버튼 추가',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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: '侧边栏新增退出登录按钮',
|
||||
|
||||
@@ -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}` },
|
||||
|
||||
Reference in New Issue
Block a user