deerflow2/backend/packages/harness/deerflow
Huixin615 8785658a2e
fix(agents): preserve todos state across node updates (#3180)
* fix(agents): preserve todos state across node updates

ThreadState.todos had no reducer, so any downstream node returning a
partial state without todos was implicitly setting it to None, which
LangGraph then used to overwrite the previously streamed value. This
caused the to-do list to render correctly during streaming but vanish
once streaming completed.

Add a merge_todos reducer that keeps the last non-None value, mirroring
the merge_artifacts pattern already used in the same file. An explicit
empty list is still respected so that 'user cleared todos' works.

Tests: 10 new unit tests in tests/test_thread_state_reducers.py covering
merge_todos plus regression coverage for merge_artifacts and
merge_viewed_images. All 69 thread-related tests pass locally.

Closes #3123

* test(agents): add annotation binding regression guard

Address Copilot review feedback on #3123:

- Add TestThreadStateAnnotations asserting that ThreadState.todos is
  Annotated with merge_todos. Without this guard, reverting the
  Annotated[list | None, merge_todos] binding would silently regress
  #3123 while all existing reducer unit tests continue to pass.

- Align test imports to 'from deerflow.agents.thread_state import ...'
  matching the rest of the backend test suite.
2026-05-23 23:25:38 +08:00
..
agents fix(agents): preserve todos state across node updates (#3180) 2026-05-23 23:25:38 +08:00
community fix(sandbox): avoid blocking sandbox readiness polling (#2822) 2026-05-21 14:44:34 +08:00
config fix(runtime): suppress tool execution when provider safety-terminates with tool_calls (#3035) 2026-05-22 21:20:28 +08:00
guardrails feat(guardrails): add pre-tool-call authorization middleware with pluggable providers (#1240) 2026-03-23 18:07:33 +08:00
mcp fix(mcp): persist MCP sessions across tool calls for stateful servers (#3089) 2026-05-21 23:22:20 +08:00
models fix(tracing): propagate session_id and user_id into Langfuse traces (#2944) 2026-05-21 16:49:31 +08:00
persistence fix: harden run finalization persistence (#3155) 2026-05-23 00:09:06 +08:00
reflection refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
runtime fix(runtime): make run creation persistence atomic (#3152) 2026-05-23 22:43:34 +08:00
sandbox fix(runtime): bound write_file execution-failure observations (#3133) 2026-05-21 20:35:46 +08:00
skills fix(skills): make security scanner JSON parsing robust for LLM output variations (#2987) 2026-05-17 08:59:42 +08:00
subagents fix(subagents): make subagent timeout terminal state atomic (#2583) 2026-05-18 22:19:32 +08:00
tools fix(stability): resolve P0 blockers from v2.0-m1-rc1 stability audit (#3107) (#3131) 2026-05-21 21:18:10 +08:00
tracing fix(tracing): propagate session_id and user_id into Langfuse traces (#2944) 2026-05-21 16:49:31 +08:00
uploads fix(uploads): add Windows support for safe symlink-protected uploads (#2794) 2026-05-09 18:21:54 +08:00
utils fix(gateway): return ISO 8601 timestamps from threads endpoints (#2599) 2026-05-02 15:16:16 +08:00
__init__.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
client.py fix(tracing): propagate session_id and user_id into Langfuse traces (#2944) 2026-05-21 16:49:31 +08:00