hermes - ✅(Solved) Fix [Bug]: 使用Hermes与Hermes-web-ui是总显示输出乱码 [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#28646Fetched 2026-05-20 04:02:56
View on GitHub
Comments
0
Participants
1
Timeline
4
Reactions
0
Author
Participants
Timeline (top)
labeled ×3cross-referenced ×1

Error Message

Additional Logs / Traceback (optional)

Root Cause

Root Cause Analysis (optional)

Fix Action

Fixed

PR fix notes

PR #28717: fix(api-server): preserve Unicode in OpenAI-compatible SSE tool-call payloads (#28646)

Description (problem / solution / changelog)

What does this PR do?

Hermes-web-ui — and every other OpenAI-compatible client that displays the function_call.arguments field verbatim — was rendering CJK / non-ASCII characters in tool-call payloads as their literal \uXXXX escape sequences. The issue reporter's screenshot in #28646 shows the agent's terminal tool being announced with:

[Calling tool: terminal with arguments: {"command":
 "... || echo \"\u65e0 kanban \u76ee\u5f55\""}]

…where the model actually emitted echo "无 kanban 目录" (Chinese for "no kanban directory"). The Latin em-dash inside the same payload renders correctly because the model sent it as a literal U+2014, but Python's json.dumps rewrites every CJK codepoint into the six-byte \u65e0 form whenever its default ensure_ascii=True is in effect.

Three json.dumps call sites in gateway/platforms/api_server.py produce the JSON-encoded strings that web UIs display directly — they all defaulted to ensure_ascii=True. Plus seven SSE-envelope encoders that wrap those strings re-escaped any literal non-ASCII bytes back into \uXXXX form before sending to the wire.

The fix is the smallest correct one: pass ensure_ascii=False to every wire-facing json.dumps in the file. The inner JSON object still round-trips through json.loads, so clients that do parse the arguments string keep getting the same dict back. The internal SQLite response store (json.dumps(data, default=str) at line 383) is left alone — it round-trips symmetrically and the encoding choice has no observable effect.

Related Issue

Fixes #28646

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Security fix
  • Documentation update
  • Tests (adding or improving test coverage)
  • Refactor (no behavior change)
  • New skill (bundled or hub)

Changes Made

  • gateway/platforms/api_server.py
    • _emit_tool_started — JSON-encode the arguments dict with ensure_ascii=False so the OpenAI-spec function_call.arguments string carries native Unicode.
    • _emit_tool_completed — same encoding for tool results returned as dicts (kanban_show, search responses, etc.).
    • The trimmed-arguments re-serialisation before response.completed — keeps the terminal envelope consistent with the streaming events.
    • All SSE envelope encoders (/v1/chat/completions role / content / finish / error / hermes.tool.progress chunks; /v1/responses _write_event; runs SSE payload) — ensure_ascii=False for defense in depth.
  • tests/gateway/test_api_server_cjk_unicode.py (new file, 5 tests)
    • TestFunctionCallArgumentsUnicode — pins the exact mojibake from the screenshot (无 kanban 目录) + round-trips the inner arguments JSON.
    • TestFunctionCallOutputUnicode — covers dict-shaped tool results with CJK + Latin diacritic + emoji.
    • TestResponseCompletedTrimmingUnicode — guards the re-serialisation pass that produces the terminal envelope.
    • TestChatCompletionsDeltaUnicode/v1/chat/completions delta.content with CJK + accented Latin + emoji.

How to Test

  1. Regression suite (this PR's coverage):

    pytest tests/gateway/test_api_server_cjk_unicode.py -q

    Expected: 5 passed.

  2. No regression in the existing API-server suite:

    pytest tests/gateway/test_api_server.py tests/gateway/test_api_server_cjk_unicode.py -q

    Expected: 154 passed.

  3. End-to-end reproduction of #28646 (requires an agent that emits CJK in tool calls — the easiest path is hermes-web-ui pointed at hermes serve with a Chinese-language session):

    # Pre-fix
    curl -sN http://localhost:8000/v1/responses \
      -H "Content-Type: application/json" \
      -d '{"model":"hermes-agent","input":"hermes kanban show work","stream":true}' \
      | grep -E '"arguments"' | head -1
    # → arguments contains "\u65e0 kanban \u76ee\u5f55"
    #   (web UI displays this verbatim)
    
    # Post-fix
    #   arguments contains "无 kanban 目录"
    #   (web UI renders the actual Chinese characters)

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix (no unrelated commits)
  • I've run the relevant test suites locally and all pass (154 passed across test_api_server.py + test_api_server_cjk_unicode.py)
  • I've added tests for my changes (5 regression tests, 4 of which fail on upstream/main without this PR)
  • I've tested on my platform: macOS 15 (darwin 24.6.0)

Documentation & Housekeeping

  • I've updated relevant documentation — inline comments at all three function-level call sites explain the why and reference #28646
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A (no new config keys)
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A
  • I've considered cross-platform impact (Windows, macOS) — pure-Python json encoding, no platform branches
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A (transport-only change, no tool surface affected)

Screenshots / Logs

$ pytest tests/gateway/test_api_server_cjk_unicode.py -v
tests/gateway/test_api_server_cjk_unicode.py::TestFunctionCallArgumentsUnicode::test_arguments_string_contains_native_cjk_chars PASSED
tests/gateway/test_api_server_cjk_unicode.py::TestFunctionCallArgumentsUnicode::test_arguments_string_is_still_valid_inner_json PASSED
tests/gateway/test_api_server_cjk_unicode.py::TestFunctionCallOutputUnicode::test_tool_result_dict_preserves_cjk PASSED
tests/gateway/test_api_server_cjk_unicode.py::TestResponseCompletedTrimmingUnicode::test_completed_envelope_carries_native_cjk_arguments PASSED
tests/gateway/test_api_server_cjk_unicode.py::TestChatCompletionsDeltaUnicode::test_streamed_chat_completion_delivers_native_cjk_in_delta PASSED
5 passed in 1.76s

Reverting the fix on upstream/main and re-running the new suite:

FAILED tests/gateway/test_api_server_cjk_unicode.py::TestFunctionCallOutputUnicode::test_tool_result_dict_preserves_cjk
FAILED tests/gateway/test_api_server_cjk_unicode.py::TestFunctionCallArgumentsUnicode::test_arguments_string_contains_native_cjk_chars
FAILED tests/gateway/test_api_server_cjk_unicode.py::TestResponseCompletedTrimmingUnicode::test_completed_envelope_carries_native_cjk_arguments
FAILED tests/gateway/test_api_server_cjk_unicode.py::TestChatCompletionsDeltaUnicode::test_streamed_chat_completion_delivers_native_cjk_in_delta
4 failed, 1 passed

The one passing test (test_arguments_string_is_still_valid_inner_json) checks the JSON.parse round-trip — that invariant holds under both encodings and exists specifically to confirm the fix doesn't break smart clients.

Changed files

  • gateway/platforms/api_server.py (modified, +29/-10)
  • tests/gateway/test_api_server_cjk_unicode.py (added, +296/-0)

Code Example

使用Hermes與Hermes-web-ui配合使用時,Hermes-web-ui回覆訊息時總顯示輸出亂碼資訊,請求如何解决这个问题?

---
RAW_BUFFERClick to expand / collapse

Bug Description

使用Hermes与Hermes-web-ui配合使用时,Hermes-web-ui回复消息时总显示输出乱码信息,请求如何解决这个问题?

<img width="620" height="189" alt="Image" src="https://github.com/user-attachments/assets/ad270870-f546-4574-bdd6-6498ea5477a6" />

Steps to Reproduce

使用Hermes与Hermes-web-ui配合使用时,Hermes-web-ui回复消息时总显示输出乱码信息,请求如何解决这个问题?

Expected Behavior

使用Hermes与Hermes-web-ui配合使用时,Hermes-web-ui回复消息时总显示输出乱码信息,请求如何解决这个问题?

Actual Behavior

使用Hermes与Hermes-web-ui配合使用时,Hermes-web-ui回复消息时总显示输出乱码信息,请求如何解决这个问题?

Affected Component

CLI (interactive chat)

Messaging Platform (if gateway-related)

No response

Debug Report

使用Hermes與Hermes-web-ui配合使用時,Hermes-web-ui回覆訊息時總顯示輸出亂碼資訊,請求如何解决这个问题?

Operating System

macOS 26.4.2

Python Version

No response

Hermes Version

No response

Additional Logs / Traceback (optional)

Root Cause Analysis (optional)

No response

Proposed Fix (optional)

No response

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix [Bug]: 使用Hermes与Hermes-web-ui是总显示输出乱码 [1 pull requests, 1 participants]