Skip to content

Commit 33d323c

Browse files
authored
fix(code): thread session_id through forced-compaction fork (#5492)
Fix `ty` failures in `deepagents-code` after the SDK's `summarization` flow added a required `session_id: str` parameter in #5470 (`fix(sdk): offload conversation history to distinct session ID when summarizing`). The forced-compaction fork in `offload_middleware` mirrors the SDK's `_run_compact`/`_arun_compact` step sequence, but still called `_offload_to_backend` / `_aoffload_to_backend` / `_build_compact_result` without the new argument, producing 5 `error[missing-argument]` diagnostics under `make -C libs/code lint`. The fork now computes `session_id = summarization._get_session_id(runtime.state)` — placed after the cutoff-0 early return, exactly where the SDK computes it — and threads it through both calls, in sync and async paths alike. A side benefit: repeated `/offload` calls now reuse the persisted `_summarization_session_id`, so history appends to one file per session instead of fragmenting across thread-id-named files. The `sdk_offload` wrapper in `test_read_failure_never_reaches_truncating_archive_write` gains the matching parameter; the rest of the test file only touches mocks or existence guards, so no other call sites needed updating. **Release note:** this change must not ship against `deepagents==0.7.5`. It calls private SDK methods with the new `session_id` signature introduced after 0.7.5, so the `deepagents-code` release must wait until the SDK releases (pending `fix(sdk):` commit on `main`) and the pin in `pyproject.toml` is bumped to that version in a separate `chore(deps):` PR.
1 parent fa55c52 commit 33d323c

3 files changed

Lines changed: 16 additions & 9 deletions

File tree

libs/code/deepagents_code/offload_middleware.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -705,17 +705,20 @@ def _run_forced_compact(self, runtime: ToolRuntime) -> Command:
705705
if cutoff == 0:
706706
return self._nothing_to_compact(tool_call_id)
707707

708+
session_id = summarization._get_session_id(runtime.state)
708709
to_summarize, _ = summarization._partition_messages(effective, cutoff)
709710
summary = summarization._create_summary(to_summarize)
710711
backend = self._guarded_backend()
711-
file_path = summarization._offload_to_backend(backend, to_summarize)
712+
file_path = summarization._offload_to_backend(
713+
backend, to_summarize, session_id
714+
)
712715
# The inherited `_build_compact_result` produces the same event and
713716
# tool message as the SDK's gated path via model-independent helpers
714717
# (string formatting + a staticmethod), so the runtime-selected
715718
# summarizer is not needed to build it. Kept inside the `try` so a
716719
# failure here still returns a ToolMessage rather than raising.
717720
return self._build_compact_result(
718-
runtime, to_summarize, summary, file_path, event, cutoff
721+
runtime, to_summarize, summary, file_path, event, cutoff, session_id
719722
)
720723
except Exception as exc: # tool errors must surface as ToolMessages
721724
logger.exception("forced compact_conversation failed")
@@ -740,14 +743,17 @@ async def _arun_forced_compact(self, runtime: ToolRuntime) -> Command:
740743
if cutoff == 0:
741744
return self._nothing_to_compact(tool_call_id)
742745

746+
session_id = summarization._get_session_id(runtime.state)
743747
to_summarize, _ = summarization._partition_messages(effective, cutoff)
744748
summary = await summarization._acreate_summary(to_summarize)
745749
backend = self._guarded_backend()
746-
file_path = await summarization._aoffload_to_backend(backend, to_summarize)
750+
file_path = await summarization._aoffload_to_backend(
751+
backend, to_summarize, session_id
752+
)
747753
# See `_run_forced_compact` for why the inherited builder is reused
748754
# and why it stays inside the `try`.
749755
return self._build_compact_result(
750-
runtime, to_summarize, summary, file_path, event, cutoff
756+
runtime, to_summarize, summary, file_path, event, cutoff, session_id
751757
)
752758
except Exception as exc: # tool errors must surface as ToolMessages
753759
logger.exception("forced compact_conversation failed")

libs/code/tests/unit_tests/test_compact_tool.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -537,10 +537,10 @@ async def test_read_failure_never_reaches_truncating_archive_write(self) -> None
537537
summarization._filter_summary_messages.side_effect = lambda messages: messages
538538

539539
async def sdk_offload(
540-
guarded: BackendProtocol, messages: list[AnyMessage]
540+
guarded: BackendProtocol, messages: list[AnyMessage], session_id: str
541541
) -> str | None:
542542
return await SummarizationMiddleware._aoffload_to_backend(
543-
summarization, guarded, messages
543+
summarization, guarded, messages, session_id
544544
)
545545

546546
summarization._aoffload_to_backend = AsyncMock(side_effect=sdk_offload)

libs/code/tests/unit_tests/test_end_to_end.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,10 @@ def test_cli_agent_summarizes(self, tmp_path: Path) -> None:
241241
# mode the history prefix lives under the backend's `artifacts_root`
242242
# (a per-session temp dir), routed to persistent storage.
243243
assert backend.ls(f"{backend.artifacts_root}/conversation_history/").entries
244-
assert (
245-
tmp_path / ".deepagents" / "conversation_history" / f"{thread_id}.md"
246-
).exists()
244+
history_files = list(
245+
(tmp_path / ".deepagents" / "conversation_history").glob("session_*.md")
246+
)
247+
assert history_files, "expected a session-id-named history file"
247248

248249
def test_cli_agent_with_fake_llm_with_tools(self, tmp_path: Path) -> None:
249250
"""Test CLI agent with tools using a fake LLM model.

0 commit comments

Comments
 (0)