feat(pi): add session resume shorthand (#113)

This commit is contained in:
banteg
2026-01-13 05:42:17 +04:00
committed by GitHub
parent c1205cd5a8
commit d4aad8e068
6 changed files with 198 additions and 18 deletions
+90 -8
View File
@@ -29,22 +29,24 @@ def _load_fixture(name: str) -> list[pi_schema.PiEvent]:
return events
def test_pi_resume_format_and_extract() -> None:
def test_pi_resume_format_and_extract(tmp_path: Path) -> None:
runner = PiRunner(
extra_args=[],
model=None,
provider=None,
)
token = ResumeToken(engine=ENGINE, value="/tmp/pi/session.jsonl")
session_path = tmp_path / "session.jsonl"
token = ResumeToken(engine=ENGINE, value=str(session_path))
assert runner.format_resume(token) == "`pi --session /tmp/pi/session.jsonl`"
assert runner.extract_resume("`pi --session /tmp/pi/session.jsonl`") == token
assert runner.extract_resume('pi --session "/tmp/pi/session.jsonl"') == token
assert runner.format_resume(token) == f"`pi --session {session_path}`"
assert runner.extract_resume(f"`pi --session {session_path}`") == token
assert runner.extract_resume(f'pi --session "{session_path}"') == token
assert runner.extract_resume("`codex resume sid`") is None
spaced = ResumeToken(engine=ENGINE, value="/tmp/pi session.jsonl")
assert runner.format_resume(spaced) == '`pi --session "/tmp/pi session.jsonl"`'
assert runner.extract_resume('`pi --session "/tmp/pi session.jsonl"`') == spaced
spaced_path = tmp_path / "pi session.jsonl"
spaced = ResumeToken(engine=ENGINE, value=str(spaced_path))
assert runner.format_resume(spaced) == f'`pi --session "{spaced_path}"`'
assert runner.extract_resume(f'`pi --session "{spaced_path}"`') == spaced
def test_translate_success_fixture() -> None:
@@ -97,6 +99,86 @@ def test_translate_error_fixture() -> None:
assert completed.answer == "Request failed."
def test_session_id_promotion_from_file(tmp_path: Path) -> None:
session_path = tmp_path / "session.jsonl"
session_path.write_text(
'{"type":"session","version":3,'
'"id":"ccd569e0-4e1b-4c7d-a981-637ed4107310",'
'"timestamp":"2026-01-13T00:33:34.702Z",'
'"cwd":"/tmp"}\n',
encoding="utf-8",
)
runner = PiRunner(
extra_args=[],
model=None,
provider=None,
)
with patch(
"takopi.runners.pi.PiRunner._new_session_path",
return_value=str(session_path),
):
state = runner.new_state("prompt", None)
events = translate_pi_event(
pi_schema.AgentStart(), title="pi", meta=None, state=state
)
started = next(evt for evt in events if isinstance(evt, StartedEvent))
assert started.resume.value == "ccd569e0"
def test_extract_resume_prefers_session_id(tmp_path: Path) -> None:
session_path = tmp_path / "session.jsonl"
session_path.write_text(
'{"type":"session","version":3,'
'"id":"ccd569e0-4e1b-4c7d-a981-637ed4107310",'
'"timestamp":"2026-01-13T00:33:34.702Z",'
'"cwd":"/tmp"}\n',
encoding="utf-8",
)
runner = PiRunner(
extra_args=[],
model=None,
provider=None,
)
token = runner.extract_resume(f"pi --session {session_path}")
assert token is not None
assert token.value == "ccd569e0"
@pytest.mark.anyio
async def test_run_normalizes_resume_path(tmp_path: Path) -> None:
session_path = tmp_path / "session.jsonl"
session_path.write_text(
'{"type":"session","version":3,'
'"id":"ccd569e0-4e1b-4c7d-a981-637ed4107310",'
'"timestamp":"2026-01-13T00:33:34.702Z",'
'"cwd":"/tmp"}\n',
encoding="utf-8",
)
runner = PiRunner(
extra_args=[],
model=None,
provider=None,
)
seen_resume: ResumeToken | None = None
async def run_stub(_prompt: str, resume: ResumeToken | None):
nonlocal seen_resume
seen_resume = resume
yield CompletedEvent(
engine=ENGINE,
resume=resume,
ok=True,
answer="ok",
)
runner.run_impl = run_stub # type: ignore[assignment]
resume = ResumeToken(engine=ENGINE, value=str(session_path))
async for _event in runner.run("test", resume):
pass
assert seen_resume is not None
assert seen_resume.value == "ccd569e0"
@pytest.mark.anyio
async def test_run_serializes_same_session() -> None:
runner = PiRunner(