zeph-session 0.22.4

Conversation-session persistence: append-only JSONL event log, replay, and fork engine
Documentation

zeph-session

Crates.io docs.rs License: MIT OR Apache-2.0 MSRV

Conversation-session persistence for Zeph: an append-only JSONL event log, deterministic replay, and fork engine, shared by every channel (CLI, TUI, Telegram, ACP, zeph serve).

[!NOTE] Implements spec-068 (issue #5343): the SessionEvent schema, the JSONL event log with torn-append recovery, the acp_sessions metadata store, the deterministic replay engine, the Condenser trait contract and its default LlmCondenser, and the eager-copy ForkEngine. It is consumed by zeph-core (agent-loop SessionSink wiring, zeph serve per-session actors, /conv commands) and zeph-acp (session load/list/fork/resume handlers).

Overview

Every conversation-session's history is appended as one line per event to <data_dir>/<session_id>/events.jsonl — the source of truth. The existing acp_sessions table (promoted from ACP-only to channel-agnostic, per spec-068 Decision D1) tracks lightweight queryable metadata (last_seq, status, fork provenance) so sessions list and reconciliation on open don't require replaying every log.

Replay never calls the LLM or a tool executor: it folds previously recorded events into agent-ready Messages, which is the correctness guarantee behind byte-identical resume and fork.

Architectural placement

zeph-session mirrors the append-only journal design of zeph-durable (sequential ordering, single-writer actor model) but is a separate crate — the two record different concerns (task/step effect-idempotency vs. conversation semantics) at different abstraction levels and use different storage formats. zeph-session does not depend on zeph-durable, and vice versa.

See specs/068-session-persistence/spec.md and plan.md for the full design and phased rollout.

Module map

Module Description
event SessionEvent tagged enum and its SessionEventEnvelope on-disk wrapper
log SessionEventLog — append-only JSONL writer/reader with torn-append truncation (INV-SP-2)
store SessionStore — CRUD over the acp_sessions metadata index
replay ReplayEngine — deterministic fold of an event log into agent-ready messages; never calls the LLM
condenser Condenser trait contract and the non-overlap guard (INV-SP-4)
llm_condenser LlmCondenser — default Condenser, reusing zeph_context::summarization
fork ForkEngine — eager-copy session forking; blobs referenced by UserMessage.image_refs are hard-linked into the child session's blobs directory (falling back to a copy), with referenced hashes validated as bare hex to prevent path traversal
error SessionError — crate-wide error enum

Usage

The on-disk layout for one session is derived from the data directory and session id:

use std::path::Path;

let dir = zeph_session::session_dir(Path::new(".zeph/sessions"), "abc-123");
assert_eq!(dir, Path::new(".zeph/sessions/abc-123"));

migrate_legacy_session_layout is a one-time startup migration that moves session directories still sitting at the pre-fix on-disk layout (<data_dir>/sessions/<session_id>/) up one level to the current layout, returning a MigrationReport (counts migrated vs. skipped-because-destination-exists).

Features

Exactly one storage backend must be selected for the acp_sessions metadata index; sqlite is the default.

Feature Default Description
sqlite yes SQLite backend for zeph-db
postgres no PostgreSQL backend for zeph-db
test-utils no Enables testcontainers-based PostgreSQL integration test utilities (implies postgres)

Installation

cargo add zeph-session

License

Licensed under either of MIT or Apache License, Version 2.0 at your option.