fix(code): recognize in-flight trace messages (#5738)

`/trace` no longer claims a thread is empty while its first user turn is
still finishing.

---

The empty-thread check previously relied only on checkpoint state, which
can lag behind the visible response until the turn exits. It now
recognizes the locally active user message while preserving the existing
checkpoint and fail-open behavior.

Verified with focused `/trace` and conversation-message unit tests plus
scoped Ruff and ty checks.

Made by [Open
SWE](https://openswe.vercel.app/agents/af6a9bd2-0d10-5856-afdc-b7cca575d418)

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
This commit is contained in:
Mason Daugherty
2026-08-23 15:06:48 -04:00
committed by GitHub
parent 23b83ad50f
commit f1d1f63281
2 changed files with 49 additions and 1 deletions
+13 -1
View File
@@ -16190,13 +16190,25 @@ class DeepAgentsApp(App):
"""Check whether the current thread has at least one human message.
Returns:
`True` if the conversation contains a `HumanMessage`, `False`
`True` if the conversation contains a `HumanMessage` or a local user
turn is still in flight (its worker has started), `False`
otherwise. On transient errors (network, corrupt state) returns
`True` so callers do not block or warn based on an unreliable
empty-thread check.
"""
if not self._agent or not self._lc_thread_id:
return False
# `_agent_turn_started` (not just `_agent_running`) is required: a
# message that failed to send (agent unavailable) leaves
# `_active_user_message` mounted, and a later non-message operation
# such as goal-criteria generation also sets `_agent_running`. Only a
# turn whose worker actually started means the prompt is in flight.
if (
self._agent_running
and self._agent_turn_started
and self._active_user_message is not None
):
return True
try:
# Use the shared helper so the thread is registered first
# (`aensure_thread`, remote agents only) in server mode — otherwise
+36
View File
@@ -24615,6 +24615,42 @@ class TestHasConversationMessages:
assert await app._has_conversation_messages() is False
async def test_returns_true_for_inflight_user_message(self) -> None:
"""Should detect a submitted user turn before its checkpoint commits."""
app = DeepAgentsApp()
async with app.run_test():
app._agent = AsyncMock()
app._lc_thread_id = "t1"
app._agent_running = True
app._agent_turn_started = True
app._active_user_message = UserMessage("hi")
assert await app._has_conversation_messages() is True
async def test_ignores_unsent_message_during_non_message_operation(self) -> None:
"""A prompt retained from a failed send must not suppress the warning.
If the agent was unavailable when the user submitted, `_send_to_agent`
reports the error but never clears `_active_user_message`. A later
operation that reserves `_agent_running` (e.g. goal-criteria
generation) must not make the empty thread look non-empty.
"""
app = DeepAgentsApp()
async with app.run_test():
state = MagicMock()
state.values = {}
agent = AsyncMock()
agent.aget_state = AsyncMock(return_value=state)
app._agent = agent
app._lc_thread_id = "t1"
# Busy from a non-message operation; the mounted prompt was never
# sent, so its worker never started a turn.
app._agent_running = True
app._agent_turn_started = False
app._active_user_message = UserMessage("hi")
assert await app._has_conversation_messages() is False
async def test_returns_false_when_only_system_messages(self) -> None:
"""Should return False when messages list has no HumanMessage."""
from langchain_core.messages import SystemMessage