mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-08 13:12:08 +00:00
fix: make streaming reasoning-tag filter case-insensitive
The streaming think-tag suppressors in cli.py (_stream_delta) and gateway/stream_consumer.py (_filter_and_accumulate) matched tag names with case-sensitive str.find(), so only the exact-case literals in the tag tuples were caught. Mixed-case variants a model may emit — <Think>, <ThInK>, <REASONING>, <Thought> — slipped through and leaked raw reasoning into the user-visible stream. Match against a lowercased view of the buffer with lowercased tag names at all three sites (open-tag boundary search, partial-tag hold-back, close-tag search) in both paths. Only KNOWN tag names are matched — no substring matching — and the block-boundary gating that protects prose mentions of <think> is preserved. - 6 parametrized case-insensitive regression tests in each of tests/gateway/test_stream_consumer.py and tests/cli/test_stream_delta_think_tag.py. Salvaged from PR #27289 by @YLChen-007.
This commit is contained in:
parent
f049227f31
commit
e23f723389
5 changed files with 46 additions and 7 deletions
14
cli.py
14
cli.py
|
|
@ -5443,10 +5443,14 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin):
|
|||
self._stream_last_was_newline = True # start of stream = boundary
|
||||
|
||||
if not getattr(self, "_in_reasoning_block", False):
|
||||
# Case-insensitive matching against a lowercased view so
|
||||
# mixed-case tag variants (<Think>, <THINKING>, …) are caught.
|
||||
prefilt_lower = self._stream_prefilt.lower()
|
||||
for tag in _OPEN_TAGS:
|
||||
tag_lower = tag.lower()
|
||||
search_start = 0
|
||||
while True:
|
||||
idx = self._stream_prefilt.find(tag, search_start)
|
||||
idx = prefilt_lower.find(tag_lower, search_start)
|
||||
if idx == -1:
|
||||
break
|
||||
# Check if this is a block boundary position
|
||||
|
|
@ -5486,11 +5490,12 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin):
|
|||
|
||||
# Could also be a partial open tag at the end — hold it back
|
||||
if not getattr(self, "_in_reasoning_block", False):
|
||||
# Check for partial tag match at the end
|
||||
# Check for partial tag match at the end (case-insensitive)
|
||||
safe = self._stream_prefilt
|
||||
for tag in _OPEN_TAGS:
|
||||
tag_lower = tag.lower()
|
||||
for i in range(1, len(tag)):
|
||||
if self._stream_prefilt.endswith(tag[:i]):
|
||||
if prefilt_lower.endswith(tag_lower[:i]):
|
||||
safe = self._stream_prefilt[:-i]
|
||||
break
|
||||
if safe:
|
||||
|
|
@ -5503,8 +5508,9 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin):
|
|||
# Keep accumulating _stream_prefilt because close tags can arrive
|
||||
# split across multiple tokens (e.g. "</REASONING_SCRATCH" + "PAD>...").
|
||||
if getattr(self, "_in_reasoning_block", False):
|
||||
prefilt_lower = self._stream_prefilt.lower()
|
||||
for tag in _CLOSE_TAGS:
|
||||
idx = self._stream_prefilt.find(tag)
|
||||
idx = prefilt_lower.find(tag.lower())
|
||||
if idx != -1:
|
||||
self._in_reasoning_block = False
|
||||
# When show_reasoning is on, route inner content to
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue