Files
hermes-web-ui/package.json
T
ekko cd14bb1963 feat: add Anthropic format conversion for chat runs and improvements (#347)
* fix: improve chat compression and tool display

Context Compression Fixes:
- Remove duplicate token calculation in compress()
- Simplify compress() to only execute compression, not judge
- Add buildConversationHistory() to preserve tool calls in LLM context
- Remove unused estimateMessagesTokens() and contextLength parameter
- Move all judgment logic to chat-run-socket.ts (uses accurate DB tokens)

Tool Call Display Improvements:
- Add tool execution duration display (format: 1.272s)
- Add success/error status icons with circular backgrounds
- Replace text error with SVG icon (X in red circle)
- Replace old checkmark with polished green checkmark icon
- Add i18n key 'chat.executionDuration' for all locales

Bug Fixes:
- Fix streaming-indicator stuck by adding try-finally in handleEvent
- Add debug logging for compression flow diagnosis
- Fix template syntax error in MessageList.vue

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(chat): convert conversation history to Anthropic format before sending to Gateway

- Add convertToAnthropicFormat() to transform OpenAI format to Anthropic format
- Handle DeepSeek reasoning_content in thinking blocks
- Properly convert tool_use and tool_result blocks
- Add convertFromAnthropicFormat() for parsing SSE responses
- Handle stringified Python arrays in resume messages
- Record debug history files for troubleshooting (original vs converted)
- Fix tool_call_id validation to prevent empty ID errors
- Clean internal Hermes fields (call_id, response_item_id) from tool_calls

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(chat): optimize message parsing and add debug logging

- Only check for stringified arrays in assistant messages (performance)
- Improve parsing error handling: keep original content on parse failure
- Add debug logging for upstream events (reasoning/thinking tracking)
- Log run.completed event keys for troubleshooting

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(chat): add message pagination and reasoning sync improvements

**Message Pagination:**
- Add getSessionDetailPaginated() for paginated message loading
- Query with DESC order then reverse in code for optimal performance
- Remove listSessionsPaginated() (not needed)

**Reasoning Sync:**
- Add bidirectional reasoning merge in syncFromHermes
  - Memory → DB: preserve streamed reasoning from SSE events
  - DB → Memory: restore reasoning if Hermes Gateway fixes storage
- Send resumed event after sync completes with complete messages
- Fix reasoning field inconsistency: use unified 'reasoning' field

**Message Parsing:**
- Only parse stringified arrays for assistant messages (performance)
- Improve parse error handling: keep original content on failure
- Add debug logging for upstream reasoning/thinking events

**Bug Fixes:**
- Fix reasoning content display: now works on both SSE and resume
- Ensure reasoning is preserved across page refreshes via sync + resumed event

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: increase default pagination limit for messages to 500

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: remove auto-resumed event trigger and clean up debug code

- Remove automatic resumed event trigger in syncFromHermes to avoid timing issues
- Clean up unused imports (fs, join)
- Remove debug history file logging code
- Fix socket parameter passing in handleAbort, markCompleted, and syncFromHermes
- Change usage emit from room broadcast to socket-only emit
- Remove console.log debug statement

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: use reasoning field in convertToAnthropicFormat

Change convertToAnthropicFormat to read from reasoning field instead
of reasoning_content for consistency with database schema and frontend.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: parse stringified array content and improve logs

- Parse stringified array format in run.completed to extract thinking/text/tool_use
- Send parsed content to frontend via parsed_content/parsed_reasoning/parsed_tool_calls
- Frontend updates last assistant message with parsed content
- Remove ellipsis from log messages, show full content
- Add detailed logging for conversion and parsing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: move finalOutputTrimmed outside else block

* fix(chat): handle double-serialized content in resumeSession

- Remove outer quotes before parsing stringified array format
- Updated changelog for v0.5.2 and v0.5.3 with multilingual support
- Fixed message pagination with DESC query + array reverse

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(chat): improve error logging for resume parsing

- Add detailed logging for double-serialized content parsing
- Log content preview when parsing fails to diagnose issues

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* revert(chat): use simple Python-to-JSON replacement

- Revert to simple .replace(/'/g, '"') approach
- Parsing failures will keep original content as-is

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 16:40:37 +08:00

121 lines
3.2 KiB
JSON

{
"name": "hermes-web-ui",
"version": "0.5.3",
"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",
"url": "https://github.com/EKKOLearnAI/hermes-web-ui.git"
},
"homepage": "https://github.com/EKKOLearnAI/hermes-web-ui",
"license": "MIT",
"engines": {
"node": ">=23.0.0"
},
"keywords": [
"hermes",
"hermes-agent",
"hermes-web",
"agent",
"ai",
"ai-agent",
"ai-chat",
"ai-dashboard",
"chatgpt",
"claude",
"openai",
"gemini",
"deepseek",
"llm",
"multi-model",
"chat-ui",
"dashboard",
"self-hosted",
"telegram",
"discord",
"slack",
"whatsapp",
"matrix",
"feishu",
"weixin",
"multi-platform",
"vue3",
"typescript"
],
"bin": {
"hermes-web-ui": "./bin/hermes-web-ui.mjs"
},
"scripts": {
"start": "vite --host --port 8648",
"dev": "concurrently \"npm run dev:server\" \"npm run dev:client\"",
"dev:client": "vite --host",
"dev:server": "nodemon --signal SIGTERM --watch packages/server/src -e ts,tsx --exec TS_NODE_PROJECT=packages/server/tsconfig.json node -r ts-node/register packages/server/src/index.ts",
"build": "vue-tsc -b && vite build && tsc --noEmit -p packages/server/tsconfig.json && node scripts/build-server.mjs",
"prepare": "[ -d dist ] || npm run build",
"preview": "NODE_ENV=production vite preview",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage"
},
"files": [
"bin/",
"dist/"
],
"dependencies": {
"eventsource": "^4.1.0",
"js-tiktoken": "^1.0.21",
"node-pty": "^1.1.0",
"socket.io": "^4.8.3",
"socket.io-client": "^4.8.3"
},
"devDependencies": {
"@koa/bodyparser": "^5.0.0",
"@koa/cors": "^5.0.0",
"@koa/router": "^15.4.0",
"@multiavatar/multiavatar": "^1.0.7",
"@pinia/testing": "^1.0.3",
"@types/eventsource": "^1.1.15",
"@types/js-yaml": "^4.0.9",
"@types/koa": "^2.15.0",
"@types/koa__cors": "^5.0.0",
"@types/koa__router": "^12.0.5",
"@types/koa-send": "^4.1.6",
"@types/koa-static": "^4.0.4",
"@types/markdown-it": "^14.1.2",
"@types/node": "^24.12.2",
"@types/qrcode": "^1.5.6",
"@types/ws": "^8.18.1",
"@vitejs/plugin-vue": "^6.0.5",
"@vue/test-utils": "^2.4.6",
"@vue/tsconfig": "^0.9.1",
"@xterm/addon-fit": "^0.11.0",
"@xterm/addon-web-links": "^0.12.0",
"@xterm/xterm": "^6.0.0",
"axios": "^1.9.0",
"concurrently": "^9.2.1",
"highlight.js": "^11.11.1",
"js-yaml": "^4.1.1",
"jsdom": "^27.0.1",
"koa": "^2.15.3",
"koa-send": "^5.0.1",
"koa-static": "^5.0.0",
"markdown-it": "^14.1.1",
"mermaid": "^11.14.0",
"monaco-editor": "^0.55.1",
"naive-ui": "^2.44.1",
"nodemon": "^3.1.14",
"pinia": "^3.0.4",
"pino": "^10.3.1",
"pino-pretty": "^13.1.3",
"qrcode": "^1.5.4",
"sass": "^1.99.0",
"ts-node": "^10.9.2",
"typescript": "~6.0.2",
"vite": "^8.0.4",
"vitest": "^3.2.4",
"vue": "^3.5.32",
"vue-i18n": "^11.3.2",
"vue-router": "^4.6.4",
"vue-tsc": "^3.2.6",
"ws": "^8.20.0"
}
}