Fix streaming agent interactions (#570)

* Fix observer, thought streaming

* Fix end of message indicators

* Remove double-delivery of answer
This commit is contained in:
cybermaggedon 2025-11-28 16:25:57 +00:00 committed by GitHub
parent 1948edaa50
commit e24de6081f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 54 additions and 15 deletions

View file

@ -256,7 +256,11 @@ class AgentManager:
# Send any new thought chunks
for i in range(prev_thought_count, len(thought_chunks)):
logger.info(f"DEBUG: Sending thought chunk {i}")
await think(thought_chunks[i])
# Mark last chunk as final if parser has moved out of THOUGHT state
is_last = (i == len(thought_chunks) - 1)
is_thought_complete = parser.state.value != "thought"
is_final = is_last and is_thought_complete
await think(thought_chunks[i], is_final=is_final)
# Send any new answer chunks
for i in range(prev_answer_count, len(answer_chunks)):
@ -376,7 +380,7 @@ class AgentManager:
logger.info(f"resp: {resp}")
await observe(resp)
await observe(resp, is_final=True)
act.observation = resp

View file

@ -214,16 +214,16 @@ class Processor(AgentService):
logger.debug(f"History: {history}")
async def think(x):
async def think(x, is_final=False):
logger.debug(f"Think: {x}")
logger.debug(f"Think: {x} (is_final={is_final})")
if streaming:
# Streaming format
r = AgentResponse(
chunk_type="thought",
content=x,
end_of_message=True,
end_of_message=is_final,
end_of_dialog=False,
# Legacy fields for backward compatibility
answer=None,
@ -242,16 +242,16 @@ class Processor(AgentService):
await respond(r)
async def observe(x):
async def observe(x, is_final=False):
logger.debug(f"Observe: {x}")
logger.debug(f"Observe: {x} (is_final={is_final})")
if streaming:
# Streaming format
r = AgentResponse(
chunk_type="observation",
content=x,
end_of_message=True,
end_of_message=is_final,
end_of_dialog=False,
# Legacy fields for backward compatibility
answer=None,
@ -352,14 +352,14 @@ class Processor(AgentService):
if streaming:
# Streaming format - send end-of-dialog marker
# Answer chunks were already sent via think() callback during parsing
# Answer chunks were already sent via answer() callback during parsing
r = AgentResponse(
chunk_type="answer",
content="", # Empty content, just marking end of dialog
end_of_message=True,
end_of_dialog=True,
# Legacy fields for backward compatibility
answer=act.final,
# Legacy fields set to None - answer already sent via streaming chunks
answer=None,
error=None,
thought=None,
)