Merge branch 'main' into bb/gui
This commit is contained in:
@@ -554,23 +554,50 @@ class TestExtractReasoning:
|
||||
assert result == "from structured field"
|
||||
|
||||
|
||||
class TestCleanSessionContent:
|
||||
def test_none_passthrough(self):
|
||||
assert AIAgent._clean_session_content(None) is None
|
||||
class TestSessionJsonSnapshotOptIn:
|
||||
"""Regression: per-session JSON snapshot writer is opt-in via config.
|
||||
|
||||
def test_scratchpad_converted(self):
|
||||
text = "<REASONING_SCRATCHPAD>think</REASONING_SCRATCHPAD> answer"
|
||||
result = AIAgent._clean_session_content(text)
|
||||
assert "<REASONING_SCRATCHPAD>" not in result
|
||||
assert "<think>" in result
|
||||
state.db is canonical (PR #29182). ``sessions.write_json_snapshots``
|
||||
defaults to False, so the agent must NOT write ``session_{sid}.json``
|
||||
files by default — that behavior caused multi-GB sessions directories
|
||||
on heavy users. Users can opt back in for external tooling that reads
|
||||
the JSON files directly.
|
||||
"""
|
||||
|
||||
def test_extra_newlines_cleaned(self):
|
||||
text = "\n\n\n<think>x</think>\n\n\nafter"
|
||||
result = AIAgent._clean_session_content(text)
|
||||
# Should not have excessive newlines around think block
|
||||
assert "\n\n\n" not in result
|
||||
# Content after think block must be preserved
|
||||
assert "after" in result
|
||||
def test_session_json_disabled_by_default(self, agent):
|
||||
# Default config: writer is gated off.
|
||||
assert getattr(agent, "_session_json_enabled", False) is False, (
|
||||
"sessions.write_json_snapshots must default to False"
|
||||
)
|
||||
|
||||
def test_save_session_log_noops_when_disabled(self, agent, tmp_path):
|
||||
# When disabled, calling the method must not write any file even
|
||||
# if logs_dir is writable and messages are non-empty.
|
||||
agent._session_json_enabled = False
|
||||
agent.logs_dir = tmp_path
|
||||
agent._session_messages = [{"role": "user", "content": "hello"}]
|
||||
agent._save_session_log()
|
||||
# No session_*.json must appear under logs_dir.
|
||||
assert list(tmp_path.glob("session_*.json")) == []
|
||||
|
||||
def test_save_session_log_writes_when_enabled(self, agent, tmp_path):
|
||||
# Opt-in path: with the flag on and a session_id, the writer must
|
||||
# produce ``session_{sid}.json`` under logs_dir.
|
||||
agent._session_json_enabled = True
|
||||
agent.logs_dir = tmp_path
|
||||
messages = [{"role": "user", "content": "hello"}]
|
||||
agent._save_session_log(messages)
|
||||
expected = tmp_path / f"session_{agent.session_id}.json"
|
||||
assert expected.exists(), (
|
||||
"Opt-in writer must produce session_{sid}.json under logs_dir"
|
||||
)
|
||||
|
||||
def test_logs_dir_retained_for_request_dumps(self, agent):
|
||||
# logs_dir is kept unconditionally because
|
||||
# agent_runtime_helpers.dump_api_request_debug still writes
|
||||
# request_dump_*.json there (debug breadcrumb path), independent of
|
||||
# the session JSON opt-in.
|
||||
assert hasattr(agent, "logs_dir")
|
||||
|
||||
|
||||
class TestGetMessagesUpToLastAssistant:
|
||||
@@ -1901,7 +1928,6 @@ class TestExecuteToolCalls:
|
||||
agent._interruptible_api_call = _fake_api_call
|
||||
agent._persist_session = lambda *args, **kwargs: None
|
||||
agent._save_trajectory = lambda *args, **kwargs: None
|
||||
agent._save_session_log = lambda *args, **kwargs: None
|
||||
|
||||
captured = io.StringIO()
|
||||
agent._print_fn = lambda *args, **kw: print(*args, file=captured, **kw)
|
||||
@@ -4253,22 +4279,6 @@ class TestSafeWriter:
|
||||
assert inner.getvalue() == "test"
|
||||
|
||||
|
||||
class TestSaveSessionLogAtomicWrite:
|
||||
def test_uses_shared_atomic_json_helper(self, agent, tmp_path):
|
||||
agent.session_log_file = tmp_path / "session.json"
|
||||
messages = [{"role": "user", "content": "hello"}]
|
||||
|
||||
with patch("run_agent.atomic_json_write", create=True) as mock_atomic_write:
|
||||
agent._save_session_log(messages)
|
||||
|
||||
mock_atomic_write.assert_called_once()
|
||||
call_args = mock_atomic_write.call_args
|
||||
assert call_args.args[0] == agent.session_log_file
|
||||
payload = call_args.args[1]
|
||||
assert payload["session_id"] == agent.session_id
|
||||
assert payload["messages"] == messages
|
||||
assert call_args.kwargs["indent"] == 2
|
||||
assert call_args.kwargs["default"] is str
|
||||
|
||||
|
||||
# ===================================================================
|
||||
@@ -5056,12 +5066,9 @@ class TestPersistUserMessageOverride:
|
||||
{"role": "assistant", "content": "Hi!"},
|
||||
]
|
||||
|
||||
with patch.object(agent, "_save_session_log") as mock_save:
|
||||
agent._persist_session(messages, [])
|
||||
agent._persist_session(messages, [])
|
||||
|
||||
assert messages[0]["content"] == "Hello there"
|
||||
saved_messages = mock_save.call_args.args[0]
|
||||
assert saved_messages[0]["content"] == "Hello there"
|
||||
first_db_write = agent._session_db.append_message.call_args_list[0].kwargs
|
||||
assert first_db_write["content"] == "Hello there"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user