fix: restore Hermes session history listing (#716)

This commit is contained in:
ekko
2026-05-14 15:23:19 +08:00
committed by GitHub
parent f6df0fecfa
commit bd6c4dc82e
13 changed files with 28 additions and 10 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "hermes-web-ui",
"version": "0.5.21",
"version": "0.5.22",
"description": "Self-hosted AI chat dashboard for Hermes Agent — multi-model web UI with multi-platform integration",
"repository": {
"type": "git",
+7
View File
@@ -5,6 +5,13 @@ export interface ChangelogEntry {
}
export const changelog: ChangelogEntry[] = [
{
version: '0.5.22',
date: '2026-05-14',
changes: [
'changelog.new_0_5_22_1',
],
},
{
version: '0.5.21',
date: '2026-05-14',
+1
View File
@@ -853,6 +853,7 @@ jobTriggered: 'Job ausgelost',
new_0_5_18_7: 'Docker single-container deployment with docker-compose and gateway startup fixes',
new_0_5_18_8: 'Fix plugins page HERMES_HOME fallback warning for non-default profiles',
new_0_5_18_9: 'Fix gateway stability across dev restarts and improve Windows compatibility',
new_0_5_22_1: 'Fix Hermes session list API reading the Web UI local session store instead of the Hermes profile database',
new_0_5_13_1: 'Nachrichtenwarteschlange für sequenzielle Run-Verarbeitung hinzugefügt, um gleichzeitige Konflikte zu vermeiden',
new_0_5_13_2: 'Zwei-Ebenen-Skills-Verzeichnisstruktur mit Sonstige-Kategorie für flache Skills unterstützt',
new_0_5_13_3: 'Temporäre Sitzungen (eph_*) beim Start-Sync filtern, um interne Sitzungen nicht zu importieren',
+1
View File
@@ -1129,6 +1129,7 @@ export default {
new_0_5_18_7: 'Docker single-container deployment with docker-compose and gateway startup fixes',
new_0_5_18_8: 'Fix plugins page HERMES_HOME fallback warning for non-default profiles',
new_0_5_18_9: 'Fix gateway stability across dev restarts and improve Windows compatibility',
new_0_5_22_1: 'Fix Hermes session list API reading the Web UI local session store instead of the Hermes profile database',
new_0_5_13_1: 'Add message queue for sequential run processing to prevent concurrent request conflicts',
new_0_5_13_2: 'Support two-level skills directory structure with misc category for flat skills',
+1
View File
@@ -849,6 +849,7 @@ jobTriggered: 'Job ejecutado',
new_0_5_18_7: 'Docker single-container deployment with docker-compose and gateway startup fixes',
new_0_5_18_8: 'Fix plugins page HERMES_HOME fallback warning for non-default profiles',
new_0_5_18_9: 'Fix gateway stability across dev restarts and improve Windows compatibility',
new_0_5_22_1: 'Fix Hermes session list API reading the Web UI local session store instead of the Hermes profile database',
new_0_5_13_1: 'Cola de mensajes para procesamiento secuencial de ejecuciones, evitando conflictos concurrentes',
new_0_5_13_2: 'Soporte para estructura de directorios de skills de dos niveles con categoría misc',
new_0_5_13_3: 'Filtrar sesiones efímeras (eph_*) durante la sincronización de inicio',
+1
View File
@@ -848,6 +848,7 @@ jobTriggered: 'Job declenche',
new_0_5_18_7: 'Docker single-container deployment with docker-compose and gateway startup fixes',
new_0_5_18_8: 'Fix plugins page HERMES_HOME fallback warning for non-default profiles',
new_0_5_18_9: 'Fix gateway stability across dev restarts and improve Windows compatibility',
new_0_5_22_1: 'Fix Hermes session list API reading the Web UI local session store instead of the Hermes profile database',
new_0_5_13_1: 'File d\'attente de messages pour le traitement séquentiel des exécutions, évitant les conflits concurrents',
new_0_5_13_2: 'Prise en charge de la structure de répertoire de skills à deux niveaux avec catégorie divers',
new_0_5_13_3: 'Filtrer les sessions éphémères (eph_*) lors de la synchronisation au démarrage',
+1
View File
@@ -849,6 +849,7 @@ export default {
new_0_5_18_7: 'Docker single-container deployment with docker-compose and gateway startup fixes',
new_0_5_18_8: 'Fix plugins page HERMES_HOME fallback warning for non-default profiles',
new_0_5_18_9: 'Fix gateway stability across dev restarts and improve Windows compatibility',
new_0_5_22_1: 'Fix Hermes session list API reading the Web UI local session store instead of the Hermes profile database',
new_0_5_13_1: 'メッセージキューによる順次実行処理で同時リクエストの競合を防止',
new_0_5_13_2: '2階層スキルディレクトリ構造をサポート、フラットスキルは「その他」カテゴリに分類',
new_0_5_13_3: '起動同期時に一時セッション(eph_*)をフィルタリング',
+1
View File
@@ -849,6 +849,7 @@ export default {
new_0_5_18_7: 'Docker single-container deployment with docker-compose and gateway startup fixes',
new_0_5_18_8: 'Fix plugins page HERMES_HOME fallback warning for non-default profiles',
new_0_5_18_9: 'Fix gateway stability across dev restarts and improve Windows compatibility',
new_0_5_22_1: 'Fix Hermes session list API reading the Web UI local session store instead of the Hermes profile database',
new_0_5_13_1: '메시지 큐를 통한 순차 실행 처리로 동시 요청 충돌 방지',
new_0_5_13_2: '2단계 스킬 디렉토리 구조 지원, 플랫 스킬은 기타 카테고리로 분류',
new_0_5_13_3: '시작 동기화 시 임시 세션(eph_*) 필터링',
+1
View File
@@ -849,6 +849,7 @@ jobTriggered: 'Job acionado',
new_0_5_18_7: 'Docker single-container deployment with docker-compose and gateway startup fixes',
new_0_5_18_8: 'Fix plugins page HERMES_HOME fallback warning for non-default profiles',
new_0_5_18_9: 'Fix gateway stability across dev restarts and improve Windows compatibility',
new_0_5_22_1: 'Fix Hermes session list API reading the Web UI local session store instead of the Hermes profile database',
new_0_5_13_1: 'Fila de mensagens para processamento sequencial de execuções, evitando conflitos concorrentes',
new_0_5_13_2: 'Suporte à estrutura de diretório de skills de dois níveis com categoria diversos',
new_0_5_13_3: 'Filtrar sessões efêmeras (eph_*) durante a sincronização na inicialização',
@@ -1131,6 +1131,7 @@ export default {
new_0_5_18_7: 'Docker single-container deployment with docker-compose and gateway startup fixes',
new_0_5_18_8: 'Fix plugins page HERMES_HOME fallback warning for non-default profiles',
new_0_5_18_9: 'Fix gateway stability across dev restarts and improve Windows compatibility',
new_0_5_22_1: '修復 Hermes 會話列表介面錯誤讀取 Web UI 本地會話庫的問題',
new_0_5_13_1: '新增訊息佇列,順序處理執行請求,避免並發衝突',
new_0_5_13_2: '支援二級 Skills 目錄結構,扁平化 Skill 歸入「雜項」分類',
new_0_5_13_3: '啟動同步時過濾暫時工作階段(eph_*),避免匯入內部工作階段',
+1
View File
@@ -1131,6 +1131,7 @@ export default {
new_0_5_18_7: 'Docker 单容器部署,更新 docker-compose 配置并修复 gateway 启动问题',
new_0_5_18_8: '修复插件页面非默认 profile 下 HERMES_HOME fallback 警告',
new_0_5_18_9: '修复 dev 模式重启时网关稳定性,改善 Windows 兼容性',
new_0_5_22_1: '修复 Hermes 会话列表接口错误读取 Web UI 本地会话库的问题',
new_0_5_13_1: '新增消息队列,顺序处理运行请求,避免并发冲突',
new_0_5_13_2: '支持二级 Skills 目录结构,扁平化 Skill 归入"杂项"分类',
@@ -114,7 +114,7 @@ export async function listHermesSessions(ctx: any) {
const profile = getActiveProfileName()
const effectiveLimit = limit && limit > 0 ? limit : 2000
const allSessions = localListSessions(profile, source, effectiveLimit)
const allSessions = await listSessionSummaries(source, effectiveLimit, profile)
ctx.body = { sessions: filterPendingDeletedSessions(allSessions.filter(s => s.source !== 'api_server')) }
}
+10 -8
View File
@@ -86,18 +86,19 @@ function normalizeNullableString(value: unknown): string | null {
return String(value)
}
function titleFromPreview(preview: string): string | null {
if (!preview) return null
return preview.length > 40 ? `${preview.slice(0, 40)}...` : preview
}
function mapRow(row: Record<string, unknown>): HermesSessionRow {
const startedAt = normalizeNumber(row.started_at)
const rawTitle = normalizeNullableString(row.title)
const preview = String(row.preview || '')
// Fallback: when no explicit title, use first user message as title (same as CLI path)
const title = rawTitle || (preview ? (preview.length > 40 ? preview.slice(0, 40) + '...' : preview) : null)
return {
id: String(row.id || ''),
source: String(row.source || ''),
user_id: normalizeNullableString(row.user_id),
model: String(row.model || ''),
title,
title: normalizeNullableString(row.title),
started_at: startedAt,
ended_at: normalizeNullableNumber(row.ended_at),
end_reason: normalizeNullableString(row.end_reason),
@@ -373,12 +374,13 @@ function latestSessionInChain(chain: HermesSessionInternalRow[]): HermesSessionI
function projectSessionSummary(root: HermesSessionInternalRow, chain: HermesSessionInternalRow[]): HermesSessionRow {
const latest = latestSessionInChain(chain)
const firstPreview = chain.map(session => session.preview).find(Boolean) || root.preview
const { parent_session_id: _parentSessionId, ...rootRow } = root
return {
...rootRow,
id: latest.id,
model: latest.model || root.model,
title: latest.title || root.title,
title: latest.title || root.title || titleFromPreview(firstPreview),
ended_at: latest.ended_at,
end_reason: latest.end_reason,
message_count: latest.message_count,
@@ -392,7 +394,7 @@ function projectSessionSummary(root: HermesSessionInternalRow, chain: HermesSess
estimated_cost_usd: latest.estimated_cost_usd,
actual_cost_usd: latest.actual_cost_usd,
cost_status: latest.cost_status,
preview: latest.preview || root.preview,
preview: latest.preview || root.preview || firstPreview || '',
last_active: latest.last_active || root.last_active,
}
}
@@ -543,7 +545,7 @@ function aggregateSessionDetail(
...rootRow,
id: requestedSessionId,
source: latest.source || root.source,
title: latest.title || root.title || (firstPreview ? (firstPreview.length > 40 ? `${firstPreview.slice(0, 40)}...` : firstPreview) : null),
title: latest.title || root.title || titleFromPreview(firstPreview),
preview: latest.preview || root.preview || firstPreview || '',
model: latest.model || root.model,
ended_at: latest.ended_at,