Skip to content

Commit 72ba975

Browse files
authored
Merge pull request #22 from MiroMindAI/frontend-dev-pengxiang
feat(agent): update UI for miroflow in alignment with MiroThinker online demo
2 parents 99f7414 + e6070ac commit 72ba975

File tree

3 files changed

+857
-105
lines changed

3 files changed

+857
-105
lines changed

web_app/api/routes/tasks.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ async def get_task_status(
121121
raise HTTPException(status_code=404, detail="Task not found")
122122

123123
progress: dict = {}
124+
stored_messages: list = []
125+
124126
if task.status == "running":
125127
progress = task_executor.get_task_progress(task_id)
126128
# Update session with progress
@@ -131,9 +133,15 @@ async def get_task_status(
131133
"step_count": progress.get("step_count", 0),
132134
},
133135
)
134-
135-
# Convert messages to Message objects
136-
messages = [Message(**m) for m in progress.get("messages", [])]
136+
else:
137+
# For completed/failed/cancelled tasks, get stored messages from session
138+
session_data = session_manager._read_session(task_id)
139+
if session_data:
140+
stored_messages = session_data.get("messages", [])
141+
142+
# Convert messages to Message objects - use progress messages for running, stored for completed
143+
raw_messages = progress.get("messages", []) if progress else stored_messages
144+
messages = [Message(**m) for m in raw_messages]
137145

138146
return TaskStatusUpdate(
139147
id=task.id,

web_app/core/task_executor.py

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,17 @@ async def _run_task(
138138
# Run agent
139139
result = await agent.run(ctx)
140140

141-
# Update session with results
141+
# Get final message history before cleanup
142+
final_messages = self._get_all_messages_from_tracer(tracer)
143+
144+
# Update session with results and full message history
142145
self.session_manager.update_task(
143146
task_id,
144147
{
145148
"status": "completed",
146149
"final_answer": result.get("final_boxed_answer", ""),
147150
"summary": result.get("summary", ""),
151+
"messages": final_messages,
148152
},
149153
)
150154

@@ -169,6 +173,24 @@ async def _run_task(
169173
if task_id in self._task_tracers:
170174
del self._task_tracers[task_id]
171175

176+
def _get_all_messages_from_tracer(self, tracer: Any) -> list[dict]:
177+
"""Extract all messages from tracer for persistence."""
178+
try:
179+
with tracer._data_lock:
180+
for key, log_file in tracer._active_tasks.items():
181+
agent_states = log_file.agent_states
182+
for agent_name, state in agent_states.items():
183+
state_data = (
184+
state.state
185+
if hasattr(state, "state")
186+
else state.get("state", {})
187+
)
188+
message_history = state_data.get("message_history", [])
189+
return self._format_messages(message_history)
190+
except Exception:
191+
pass
192+
return []
193+
172194
def get_task_progress(self, task_id: str) -> dict[str, Any]:
173195
"""Get current progress from tracer."""
174196
tracer = self._task_tracers.get(task_id)
@@ -199,8 +221,8 @@ def get_task_progress(self, task_id: str) -> dict[str, Any]:
199221
current_turn = max(
200222
current_turn, (len(message_history) + 1) // 2
201223
)
202-
# Get recent messages for display
203-
messages = self._format_messages(message_history[-6:])
224+
# Get ALL messages for display (full history)
225+
messages = self._format_messages(message_history)
204226

205227
# Filter and format logs to show tool calls
206228
recent_logs = (
@@ -285,7 +307,12 @@ def _format_recent_logs(self, logs: list[dict]) -> list[dict]:
285307
return formatted[-15:]
286308

287309
def _format_messages(self, messages: list[dict]) -> list[dict]:
288-
"""Format message history for display."""
310+
"""Format message history for display.
311+
312+
Note: We do NOT truncate message content here to preserve:
313+
- Full thinking/reasoning content for proper display
314+
- Complete tool results (e.g., search results JSON) for parsing
315+
"""
289316
formatted = []
290317
for msg in messages:
291318
role = msg.get("role", "unknown")
@@ -300,9 +327,12 @@ def _format_messages(self, messages: list[dict]) -> list[dict]:
300327
if item.get("type") == "text":
301328
text_parts.append(item.get("text", ""))
302329
elif item.get("type") == "tool_result":
303-
text_parts.append(
304-
f"[Tool Result: {self._truncate_output(item.get('content', ''))}]"
305-
)
330+
# Don't truncate tool results - need full JSON for parsing
331+
tool_content = item.get("content", "")
332+
if isinstance(tool_content, str):
333+
text_parts.append(tool_content)
334+
else:
335+
text_parts.append(str(tool_content))
306336
elif item.get("type") == "tool_use":
307337
text_parts.append(f"[Tool Call: {item.get('name', '')}]")
308338
elif isinstance(item, str):
@@ -311,10 +341,11 @@ def _format_messages(self, messages: list[dict]) -> list[dict]:
311341
elif not isinstance(content, str):
312342
content = str(content)
313343

344+
# Don't truncate - preserve full content for thinking and tool results
314345
formatted.append(
315346
{
316347
"role": role,
317-
"content": self._truncate_output(content),
348+
"content": content,
318349
}
319350
)
320351

0 commit comments

Comments
 (0)