fix(ui): persist thinking/reasoning trace across page reload (fixes #427)

This commit is contained in:
Hermes Agent
2026-04-14 20:56:53 +00:00
parent 3c5ca2db62
commit f86581e3e5
2 changed files with 14 additions and 0 deletions

View File

@@ -164,6 +164,7 @@ def _run_agent_streaming(session_id, msg_text, model, workspace, stream_id, atta
try: try:
_token_sent = False # tracks whether any streamed tokens were sent _token_sent = False # tracks whether any streamed tokens were sent
_reasoning_text = '' # accumulates reasoning/thinking trace for persistence
def on_token(text): def on_token(text):
nonlocal _token_sent nonlocal _token_sent
@@ -173,8 +174,10 @@ def _run_agent_streaming(session_id, msg_text, model, workspace, stream_id, atta
put('token', {'text': text}) put('token', {'text': text})
def on_reasoning(text): def on_reasoning(text):
nonlocal _reasoning_text
if text is None: if text is None:
return return
_reasoning_text += str(text)
put('reasoning', {'text': str(text)}) put('reasoning', {'text': str(text)})
def on_tool(*cb_args, **cb_kwargs): def on_tool(*cb_args, **cb_kwargs):
@@ -546,6 +549,12 @@ def _run_agent_streaming(session_id, msg_text, model, workspace, stream_id, atta
usage['context_length'] = getattr(_cc, 'context_length', 0) or 0 usage['context_length'] = getattr(_cc, 'context_length', 0) or 0
usage['threshold_tokens'] = getattr(_cc, 'threshold_tokens', 0) or 0 usage['threshold_tokens'] = getattr(_cc, 'threshold_tokens', 0) or 0
usage['last_prompt_tokens'] = getattr(_cc, 'last_prompt_tokens', 0) or 0 usage['last_prompt_tokens'] = getattr(_cc, 'last_prompt_tokens', 0) or 0
# Persist reasoning trace in the session so it survives reload
if _reasoning_text and s.messages:
for _rm in reversed(s.messages):
if isinstance(_rm, dict) and _rm.get('role') == 'assistant':
_rm['reasoning'] = _reasoning_text
break
raw_session = s.compact() | {'messages': s.messages, 'tool_calls': tool_calls} raw_session = s.compact() | {'messages': s.messages, 'tool_calls': tool_calls}
put('done', {'session': redact_session_data(raw_session), 'usage': usage}) put('done', {'session': redact_session_data(raw_session), 'usage': usage})
finally: finally:

View File

@@ -353,6 +353,11 @@ function attachLiveStream(activeSid, streamId, uploaded=[], options={}){
} }
if(S.session&&S.session.session_id===activeSid){ if(S.session&&S.session.session_id===activeSid){
S.session=d.session;S.messages=d.session.messages||[]; S.session=d.session;S.messages=d.session.messages||[];
// Persist reasoning trace so thinking card survives page reload
if(reasoningText){
const lastAsst=[...S.messages].reverse().find(m=>m.role==='assistant');
if(lastAsst&&!lastAsst.reasoning) lastAsst.reasoning=reasoningText;
}
// Stamp _ts on the last assistant message if it has no timestamp // Stamp _ts on the last assistant message if it has no timestamp
const lastAsst=[...S.messages].reverse().find(m=>m.role==='assistant'); const lastAsst=[...S.messages].reverse().find(m=>m.role==='assistant');
if(lastAsst&&!lastAsst._ts&&!lastAsst.timestamp) lastAsst._ts=Date.now()/1000; if(lastAsst&&!lastAsst._ts&&!lastAsst.timestamp) lastAsst._ts=Date.now()/1000;