ZioSessionCatalog

works.iterative.claude.zio.log.ZioSessionCatalog
See theZioSessionCatalog companion object
class ZioSessionCatalog extends SessionCatalog[[A] =>> IO[ArchiveError, A]]

Attributes

Companion
object
Graph
Supertypes
trait SessionCatalog[[A] =>> IO[ArchiveError, A]]
class Object
trait Matchable
class Any

Members list

Type members

Types

type EntryStream = ZStream[Any, ArchiveError, ConversationLogEntry]

Value members

Concrete methods

def entries(sessionId: SessionId): EntryStream

Streams the main-thread entries of a session. Resolves vendor-then-mirror like forSession.

Streams the main-thread entries of a session. Resolves vendor-then-mirror like forSession.

Attributes

def entriesBefore(token: PageToken, limit: Int): IO[ArchiveError, EntryPage]

Reads the page of up to limit entries immediately older than token.

Reads the page of up to limit entries immediately older than token.

The token is pinned to the transcript it was minted against; if the session now resolves to a different file (the vendor tree was pruned between pages), this fails with ArchiveError.PageSourceMoved rather than reading a stale offset against the wrong file. If the session no longer resolves under either root at all, this fails with ArchiveError.SessionNotFound.

Attributes

def follow(sessionId: SessionId, limit: Int, pollEvery: Duration): ZStream[Any, ArchiveError, Followed]

Follows a session's main transcript as the agent writes it.

Follows a session's main transcript as the agent writes it.

The first element is the newest page of what the transcript already holds — the same read lastEntries makes — and every element after it is what the file has grown by since the element before. Nothing is emitted while the file is unchanged, and a line the writer has not finished is held back until it is, so an entry is read exactly once and never half-written.

The whole of what the follow remembers is a byte offset into an append-only file, so nothing that was read is held on to. The session is resolved once, vendor-then-mirror, and the offset belongs to the file that resolution found: a read that fails because that file went away — or finds a file shorter than what has already been read, which an append-only transcript never is — ends the follow, and re-subscribing resolves again.

Value parameters

limit

how many entries the opening page carries

pollEvery

how often the file is looked at for what it has grown by

Attributes

def forSession(sessionId: SessionId): IO[ArchiveError, Option[SessionRecord]]

Locates a session by its id, resolving the live vendor tree first when the cwd is known and falling back to the kept copy; None when no main transcript exists under any root. The returned record's root names which one won.

Locates a session by its id, resolving the live vendor tree first when the cwd is known and falling back to the kept copy; None when no main transcript exists under any root. The returned record's root names which one won.

Attributes

def lastEntries(sessionId: SessionId, limit: Int): IO[ArchiveError, EntryPage]

Reads the last limit main-thread entries of a session without parsing the transcript from the start. Entries within the returned page are oldest-first; the page itself is the newest slice of the transcript. The page's older cursor pages backward through earlier, older pages. Resolves vendor-then-mirror like forSession, so a pruned session still tails from the mirror.

Reads the last limit main-thread entries of a session without parsing the transcript from the start. Entries within the returned page are oldest-first; the page itself is the newest slice of the transcript. The page's older cursor pages backward through earlier, older pages. Resolves vendor-then-mirror like forSession, so a pruned session still tails from the mirror.

Attributes

def mirror(sessionId: SessionId): IO[ArchiveError, MirrorReport]

Idempotently keeps the whole session tree in the installation's kept directory, reporting what was copied, extended, refreshed, and skipped. The first keep also writes the custody-borne facts beside the transcript (works.iterative.claude.core.log.model.CustodyFacts); a later keep never rewrites them. A keep into a key another installation already holds fails with ArchiveError.InstallationKeyTaken.

Idempotently keeps the whole session tree in the installation's kept directory, reporting what was copied, extended, refreshed, and skipped. The first keep also writes the custody-borne facts beside the transcript (works.iterative.claude.core.log.model.CustodyFacts); a later keep never rewrites them. A keep into a key another installation already holds fails with ArchiveError.InstallationKeyTaken.

Custody is one-directional: when the session resolves under works.iterative.claude.core.log.model.RecordRoot.Archive (the vendor tree is already pruned), this is a no-op returning works.iterative.claude.core.log.model.MirrorReport.empty — the archive is never truncated or recopied from nothing. Only a Vendor-resolved record is ever a mirror source. SessionNotFound is raised only when neither root holds the session.

Attributes

def subagentEntries(sessionId: SessionId, parentToolUseId: String): EntryStream

Streams a sub-agent's own sidechain entries, joined to its parent by the tool_use id recorded in the sub-agent's .meta.json. Resolves vendor-then-mirror like forSession.

Streams a sub-agent's own sidechain entries, joined to its parent by the tool_use id recorded in the sub-agent's .meta.json. Resolves vendor-then-mirror like forSession.

Attributes