mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-10-06 02:48:22 +00:00
fix(agent): preserve Unicode separators in saved state (#594)
Some checks are pending
CI / OpenClaw plugin / Validate OpenClaw plugin (push) Waiting to run
CI / Python packages / Build and verify distributions (push) Waiting to run
CI / Python quality / GitHub Actions (push) Waiting to run
CI / Python quality / Pre-commit (push) Waiting to run
CI / Python tests / Unit Tests - py3.11 (push) Waiting to run
CI / Python tests / Unit Tests - py3.12 (push) Waiting to run
CI / Python tests / Unit Tests - py3.13 (push) Waiting to run
CI / Python tests / Unit Tests - py3.14 (push) Waiting to run
CI / Windows / CLI smoke - py3.11 (push) Waiting to run
CI and Release / Docker / Build and test / amd64 (push) Waiting to run
CI and Release / Docker / Build and test / arm64 (push) Waiting to run
CI and Release / Docker / Publish multi-platform tags (push) Blocked by required conditions
Security / CodeQL / Analyze javascript-typescript (push) Waiting to run
Security / CodeQL / Analyze python (push) Waiting to run
Some checks are pending
CI / OpenClaw plugin / Validate OpenClaw plugin (push) Waiting to run
CI / Python packages / Build and verify distributions (push) Waiting to run
CI / Python quality / GitHub Actions (push) Waiting to run
CI / Python quality / Pre-commit (push) Waiting to run
CI / Python tests / Unit Tests - py3.11 (push) Waiting to run
CI / Python tests / Unit Tests - py3.12 (push) Waiting to run
CI / Python tests / Unit Tests - py3.13 (push) Waiting to run
CI / Python tests / Unit Tests - py3.14 (push) Waiting to run
CI / Windows / CLI smoke - py3.11 (push) Waiting to run
CI and Release / Docker / Build and test / amd64 (push) Waiting to run
CI and Release / Docker / Build and test / arm64 (push) Waiting to run
CI and Release / Docker / Publish multi-platform tags (push) Blocked by required conditions
Security / CodeQL / Analyze javascript-typescript (push) Waiting to run
Security / CodeQL / Analyze python (push) Waiting to run
Co-authored-by: pei711 <199601925+pei711@users.noreply.github.com>
This commit is contained in:
parent
090c8c24ab
commit
dc12798526
2 changed files with 59 additions and 1 deletions
|
|
@ -65,7 +65,9 @@ class AsStateHandler:
|
|||
async def load(self) -> AgentState:
|
||||
"""Read an AgentState back from ``self.path``."""
|
||||
async with aiofiles.open(self.path, encoding="utf-8") as f:
|
||||
lines = (await f.read()).splitlines()
|
||||
# Unicode line separators are valid JSON string content, not JSONL delimiters.
|
||||
content = await f.read()
|
||||
lines = content.split("\n") if content else []
|
||||
if not lines:
|
||||
return AgentState()
|
||||
|
||||
|
|
|
|||
56
tests/unit/test_agent_state_io.py
Normal file
56
tests/unit/test_agent_state_io.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
"""AgentScope state persistence must follow JSONL record boundaries."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from agentscope.message import UserMsg
|
||||
from agentscope.state import AgentState
|
||||
|
||||
from reme.utils import AsStateHandler
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("separator", ["ordinary", "\n", "\r\n", "\u0085", "\u2028", "\u2029"])
|
||||
@pytest.mark.parametrize("field", ["summary", "context"])
|
||||
async def test_state_round_trip_preserves_text_separators(tmp_path: Path, separator: str, field: str):
|
||||
"""Valid Unicode JSON string content never creates an extra JSONL record."""
|
||||
text = f"before{separator}after"
|
||||
state = AgentState(
|
||||
session_id="unicode-session",
|
||||
reply_id="saved-reply",
|
||||
cur_iter=3,
|
||||
summary=text if field == "summary" else "ordinary summary",
|
||||
context=[UserMsg(name="user", content=text if field == "context" else "ordinary message")],
|
||||
)
|
||||
handler = AsStateHandler.for_session(tmp_path, state.session_id)
|
||||
|
||||
await handler.dump(state)
|
||||
restored = await handler.load()
|
||||
|
||||
assert restored.model_dump() == state.model_dump()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("newline", ["\n", "\r\n"])
|
||||
async def test_state_load_accepts_lf_and_crlf_records(tmp_path: Path, newline: str):
|
||||
"""Existing LF and CRLF files retain their header and context records."""
|
||||
state = AgentState(session_id="existing-session", summary="summary", context=[UserMsg(name="user", content="text")])
|
||||
handler = AsStateHandler.for_session(tmp_path, state.session_id)
|
||||
await handler.dump(state)
|
||||
content = handler.path.read_text(encoding="utf-8")
|
||||
handler.path.write_bytes(content.replace("\n", newline).encode("utf-8"))
|
||||
|
||||
assert (await handler.load()).model_dump() == state.model_dump()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_state_load_accepts_empty_file(tmp_path: Path):
|
||||
"""An empty state file continues to load as a fresh AgentState."""
|
||||
handler = AsStateHandler.for_session(tmp_path, "empty-session")
|
||||
handler.path.write_text("", encoding="utf-8")
|
||||
|
||||
restored = await handler.load()
|
||||
assert restored.summary == ""
|
||||
assert restored.context == []
|
||||
assert restored.cur_iter == 0
|
||||
assert restored.session_id
|
||||
Loading…
Add table
Reference in a new issue