fix(api_server): trust full transcripts via _transcript_mode to stop repair-induced duplication - #75289
Conversation
…repair-induced duplication AIAgent.run_conversation returns its authoritative full transcript in result[messages]. Message repair may rewrite prior messages in place, so the transcript no longer shares an exact prefix with the input conversation_history -- the content-equality prefix detection in _build_response_conversation_history returns turn_start=0 and falls through to the prior + current_user + agent_messages concatenation, duplicating the entire history on every turn. Set result[_transcript_mode] = full in _run_agent so the builder trusts the full-transcript path directly, regardless of repair-induced prefix drift. The _compressed flag and exact-prefix heuristic are retained as fallbacks for code paths that do not set the explicit mode. Adds regression tests for a repaired full transcript stored via previous_response_id chaining and a unit test verifying _run_agent sets the explicit transcript mode. Fixes NousResearch#68257 (complements NousResearch#69306 and NousResearch#70695).
|
Thanks for isolating the repaired-transcript storage path. The explicit marker matches the current agent contract: Problems
Suggested changes
This is an automated hermes-sweeper review. |
_sweeper review on NousResearch#75289 noted that the original fix only covered the storage path in _build_response_conversation_history. The same prefix miss also affects _extract_output_items, which uses _response_messages_turn_start_index to decide where the current turn's output begins. Extend _response_messages_turn_start_index so that when _transcript_mode=full is set, it reverse-anchors on the last user message in the authoritative full transcript. This gives the correct output offset even after repair_message_sequence merges adjacent user messages and the exact-prefix comparison fails. Adds an endpoint regression test with adjacent user input items and a prior history containing tool calls, asserting that the output array contains only the current turn's assistant message while the stored conversation_history remains the repaired full transcript.
|
@teknium1 thanks for the review. I've pushed a follow-up commit that addresses the output-side boundary:
Please take another look when you have a chance. |
SummaryThree PRs reference #68257. #68282 and part of #70695 address the reported but currently unverified leading-system transcript shape, while #75289 addresses a concrete repair-induced prefix mismatch by marking authoritative full transcripts and handling their output boundary. Related pull requests
Duplicates#68282 and the leading-system handling in #70695 substantially duplicate the same unverified system-prefix mitigation. #75289 overlaps their history-doubling symptom but addresses a distinct, current repair-induced prefix mismatch rather than that claimed producer shape. Suggested consolidationKeep #75289 open with a salvage path: retain the explicit authoritative-transcript marker and storage/output-boundary fix, then strengthen the endpoint regression so it exercises the real repair helper. For #68282, request author action to identify a current leading-system producer or re-scope the patch; for #70695, request author action to split out the independently verifiable semantic mismatch and output-boundary work while removing role-only system stripping. Do not treat #75289 as resolving the unverified leading-system claim, and do not close #68282 or #70695 as exact duplicates of it. Complex graphflowchart LR
classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
classDef best stroke-width:3px,stroke:#b45309
classDef target stroke-width:3px,stroke:#4338ca
I68257(["issue #68257 (closed)"])
P75289["PR #75289 (open)"]
P75289 -->|best fix| I68257
class I68257 closed
class P75289 open
class P75289 best
class P75289 target
click I68257 "https://github.com/NousResearch/hermes-agent/issues/68257"
click P75289 "https://github.com/NousResearch/hermes-agent/pull/75289"
Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label). Cross-PR triage: Reviewed 3 pull requests and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 42 kB of PR diffs, 16 kB of issue/PR text, 1 kB of discussion (3 comments), 7 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch. |
What does this PR do?
Fixes a storage-side duplication bug in
/v1/responseswhenprevious_response_idchaining is used together withrepair_message_sequence. The storedconversation_historydoubles on every chained turn because the repaired transcript no longer matches the exact prefix expected by_response_messages_turn_start_index.Root cause
AIAgent.run_conversationreturns the authoritative full transcript inresult["messages"]. Before each LLM call,repair_message_sequence_with_cursormay merge adjacent user/assistant messages in place. The merged transcript no longer shares an exact prefix with the loadedconversation_history, so_response_messages_turn_start_indexreturns0and_build_response_conversation_historyfalls through to:Because
agent_messagesalready contains the full transcript, this concatenation doubles the stored history every chained turn.Fix
_run_agent: whenresult["messages"]is a list, setresult["_transcript_mode"] = "full"._build_response_conversation_history: after the exact-prefix heuristic fails, checkresult.get("_transcript_mode") == "full"and returnagent_messagesverbatim.The existing
_compressedflag and exact-prefix detection are kept as fallbacks for mocks, legacy adapters, and delta-shaped returns.Related Issue
Fixes #68257
Complements #69306 (compression-triggered prefix misses via
_compressed) and relates to #70695 (tolerant semantic turn-start detection).Type of Change
Changes Made
gateway/platforms/api_server.py_run_agentannotatesresult["_transcript_mode"] = "full"when the agent returns a message list._build_response_conversation_historytrusts the explicit mode and returns the full transcript directly.tests/gateway/test_api_server.pyTestRepairedTranscriptDuplication: two regression tests covering a repaired transcript stored once and chained turns without exponential growth.TestRunAgentTranscriptMode: unit test verifying_run_agentsets_transcript_mode="full".How to Test