mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-15 14:22:43 +00:00
fix(compressor): pin summary role to user when only system prompt is protected (#52160)
After the first compaction protect_first_n decays, so on a later compaction the only protected head message can be the system prompt. Adapters like Anthropic and Bedrock send the system prompt as a separate parameter, so the summary becomes the first message in messages[] — and Anthropic rejects any request whose first message is not role=user (HTTP 400). Pin the summary to role=user when the head is system-only, and stop the collision-flip logic from reverting it back to assistant. Salvaged from #52167. Co-authored-by: liuhao1024 <sunsky.lau@gmail.com>
This commit is contained in:
parent
82ac7e16b8
commit
8f4d195d5f
2 changed files with 110 additions and 2 deletions
|
|
@ -2818,9 +2818,17 @@ This compaction should PRIORITISE preserving all information related to the focu
|
|||
_merge_summary_into_tail = False
|
||||
last_head_role = messages[compress_start - 1].get("role", "user") if compress_start > 0 else "user"
|
||||
first_tail_role = messages[compress_end].get("role", "user") if compress_end < n_messages else "user"
|
||||
# When the only protected head message is the system prompt, the
|
||||
# summary becomes the first *visible* message in the API request
|
||||
# (most adapters — Anthropic, Bedrock — send the system prompt as
|
||||
# a separate ``system`` parameter, not inside ``messages[]``).
|
||||
# Anthropic unconditionally rejects requests whose first message
|
||||
# is not role=user, so we must pin the summary to "user" and
|
||||
# prevent the flip logic below from reverting it (#52160).
|
||||
_force_user_leading = last_head_role == "system"
|
||||
# Pick a role that avoids consecutive same-role with both neighbors.
|
||||
# Priority: avoid colliding with head (already committed), then tail.
|
||||
if last_head_role in {"assistant", "tool"}:
|
||||
if last_head_role in {"assistant", "tool"} or _force_user_leading:
|
||||
summary_role = "user"
|
||||
else:
|
||||
summary_role = "assistant"
|
||||
|
|
@ -2828,7 +2836,7 @@ This compaction should PRIORITISE preserving all information related to the focu
|
|||
# collide with the head, flip it.
|
||||
if summary_role == first_tail_role:
|
||||
flipped = "assistant" if summary_role == "user" else "user"
|
||||
if flipped != last_head_role:
|
||||
if flipped != last_head_role and not _force_user_leading:
|
||||
summary_role = flipped
|
||||
else:
|
||||
# Both roles would create consecutive same-role messages
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue