Implement ratatoskr.sessions — create + list against Worldtree #2

Closed
opened 2026-05-20 21:44:57 -07:00 by vh · 1 comment
Owner

Problem

The --send non-interactive mode (design-brief §8b) needs to create a session before streaming when invoked with --new. The Textual TUI's startup session picker (design-brief §4) needs to list existing sessions. Both touch the session-lifecycle API but neither belongs in ratatoskr.sse_client, which is scoped to per-turn streaming.

Without these primitives, --send --new can't synthesize a fresh session against Worldtree, and the TUI picker has no source for its DataTable of GET /sessions results.

Solution

Implement src/ratatoskr/sessions.py per the contract at docs/contracts/issues/2.contract.md. Two entry points + two shared dataclasses:

  • create_session(client, agent_id) -> SessionInfo — POST /sessions.
  • list_sessions(client, *, include_archived=False, limit=50, cursor=None) -> SessionPage — GET /sessions; cursor-paginated.
  • SessionInfo — frozen dataclass carrying the shape both endpoints share (session_id, agent_id, created_at, last_active, metadata) plus list-response-only fields (name, archived, tags) typed as optional.
  • SessionPage — frozen dataclass: items: list[SessionInfo], next_cursor: str | None.

Spec-conformance discipline mirrors issue #1: no core.* / worldtree.* imports (boundary already enforced by tests/test_no_worldtree_imports.py); caller owns the httpx.AsyncClient and Authorization header lifecycle.

Out of scope (this issue)

  • Bifrost binding (Worldtree issue #160) — advanced consumer-side tools injection; Ratatoskr is not a Bifrost consumer.
  • Ephemeral / Saga sessions — separate session class with TTL semantics; not needed for the dev TUI.
  • GET /sessions/{id}, PATCH /sessions/{id}, DELETE /sessions/{id} — admin-side or mutate-side operations outside Ratatoskr's TUI surface (per design-brief §4 negative clauses: "no in-app rename", "no in-app session deletion").
  • GET /sessions/{id}/messages (history pagination) — deferred until the TUI needs scrollback-replay; not used by --send.

Benefits

  • Unblocks --send --new (the next vertical slice toward exercising sse_client end-to-end against a live Worldtree).
  • Provides the list endpoint the Textual TUI's startup picker will consume directly.
  • Keeps Ratatoskr's API-consumption surface organized along Worldtree's actual endpoint groupings: sse_client for turn streaming + cancel, sessions for session lifecycle.

Acceptance

  • All contract TESTS sections pass under uv run pytest tests/.
  • Boundary smoke test tests/test_no_worldtree_imports.py continues to pass (no Worldtree-source imports added).
  • uv run ruff check src/ tests/ clean.
  • Spec pin unchanged (Worldtree v0.19.0 / repo SHA 55101e909abcd2219833266b6f905c5bc956e0f0).

Dependencies

  • Issue #1 (ratatoskr.sse_client) closed-on-main. Not a code dependency — sessions.py does not import from sse_client.py — but a convention dependency: the API-consumption posture (caller-owned httpx client, async-native, no Worldtree imports, response-parsing into typed dataclasses) is established there and sessions.py follows the same shape.
## Problem The `--send` non-interactive mode (design-brief §8b) needs to create a session before streaming when invoked with `--new`. The Textual TUI's startup session picker (design-brief §4) needs to list existing sessions. Both touch the session-lifecycle API but neither belongs in `ratatoskr.sse_client`, which is scoped to per-turn streaming. Without these primitives, `--send --new` can't synthesize a fresh session against Worldtree, and the TUI picker has no source for its `DataTable` of `GET /sessions` results. ## Solution Implement `src/ratatoskr/sessions.py` per the contract at `docs/contracts/issues/2.contract.md`. Two entry points + two shared dataclasses: - `create_session(client, agent_id) -> SessionInfo` — POST `/sessions`. - `list_sessions(client, *, include_archived=False, limit=50, cursor=None) -> SessionPage` — GET `/sessions`; cursor-paginated. - `SessionInfo` — frozen dataclass carrying the shape both endpoints share (`session_id`, `agent_id`, `created_at`, `last_active`, `metadata`) plus list-response-only fields (`name`, `archived`, `tags`) typed as optional. - `SessionPage` — frozen dataclass: `items: list[SessionInfo]`, `next_cursor: str | None`. Spec-conformance discipline mirrors issue #1: no `core.*` / `worldtree.*` imports (boundary already enforced by `tests/test_no_worldtree_imports.py`); caller owns the `httpx.AsyncClient` and `Authorization` header lifecycle. ## Out of scope (this issue) - **Bifrost binding** (Worldtree issue #160) — advanced consumer-side tools injection; Ratatoskr is not a Bifrost consumer. - **Ephemeral / Saga sessions** — separate session class with TTL semantics; not needed for the dev TUI. - `GET /sessions/{id}`, `PATCH /sessions/{id}`, `DELETE /sessions/{id}` — admin-side or mutate-side operations outside Ratatoskr's TUI surface (per design-brief §4 negative clauses: "no in-app rename", "no in-app session deletion"). - `GET /sessions/{id}/messages` (history pagination) — deferred until the TUI needs scrollback-replay; not used by `--send`. ## Benefits - Unblocks `--send --new` (the next vertical slice toward exercising `sse_client` end-to-end against a live Worldtree). - Provides the list endpoint the Textual TUI's startup picker will consume directly. - Keeps Ratatoskr's API-consumption surface organized along Worldtree's actual endpoint groupings: `sse_client` for turn streaming + cancel, `sessions` for session lifecycle. ## Acceptance - All contract TESTS sections pass under `uv run pytest tests/`. - Boundary smoke test `tests/test_no_worldtree_imports.py` continues to pass (no Worldtree-source imports added). - `uv run ruff check src/ tests/` clean. - Spec pin unchanged (Worldtree v0.19.0 / repo SHA `55101e909abcd2219833266b6f905c5bc956e0f0`). ## Dependencies - Issue #1 (`ratatoskr.sse_client`) closed-on-main. Not a code dependency — `sessions.py` does not import from `sse_client.py` — but a convention dependency: the API-consumption posture (caller-owned httpx client, async-native, no Worldtree imports, response-parsing into typed dataclasses) is established there and `sessions.py` follows the same shape.
vh added the enhancementtask labels 2026-05-20 21:44:57 -07:00
Author
Owner

Closed — shipped. ratatoskr.sessions create+list implemented via TDD (commit 4ba143c, Volva-reviewed in d6f9327).

Closed — shipped. ratatoskr.sessions create+list implemented via TDD (commit 4ba143c, Volva-reviewed in d6f9327).
vh closed this issue 2026-05-29 23:27:31 -07:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vh/ratatoskr#2