mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-10-15 20:55:23 +02:00
In exit mode, a run stores its DeltaChannel writes on the checkpoint it started from, under synthetic task ids that put the superstep first. For a `Command`'s writes in a run whose first superstep is 0, that id came out as `NULL_TASK_ID` itself. Readers take writes under `NULL_TASK_ID` for the checkpoint's own pending writes, so after `invoke(Command(update=...), durability="exit")`: - on a new thread, `get_state` on the empty first checkpoint showed the update in the DeltaChannel but not in a plain channel; - on a thread whose first checkpoint came from `update_state(..., as_node="__input__")`, `get_state` on that checkpoint showed the update the same way, and a replay or fork from it applied the update to the DeltaChannel only. `exit_delta_task_id` now never returns `NULL_TASK_ID`. Threads already saved this way stay as they are. ## Tests - `test_command_update_on_an_input_checkpoint_matches_a_plain_channel` compares every checkpoint in the history, and a replay from the input checkpoint, with a plain channel, on every checkpointer and durability. The exit cases fail without the fix. - `test_exit_command_update_on_a_new_thread_matches_a_plain_channel` compares every checkpoint in a new thread's history with a plain channel, on every checkpointer, and fails without the fix. It runs in exit mode only: in sync and async the two channels already differ on `main`, because of a separate bug that applies a new thread's `Command` update twice. `make format`, `make lint` and the langgraph suite pass.