pub struct SessionManager { /* private fields */ }Expand description
Session tree with append-only JSONL persistence.
Implementations§
Source§impl SessionManager
impl SessionManager
Sourcepub fn append_tool_dispatch(
&mut self,
tool_call_id: &str,
tool_name: &str,
input: &JsonObject,
) -> Result<EntryId, SessionError>
pub fn append_tool_dispatch( &mut self, tool_call_id: &str, tool_name: &str, input: &JsonObject, ) -> Result<EntryId, SessionError>
Appends the TOOL_DISPATCH_TYPE record of a tool call (D-DISPATCH): a custom
entry naming the call before its body runs, so resume repair can attribute an
interrupted effect. custom entries never project into context
(session-manager.js:164-181) — inert to v3-format readers.
§Errors
I/O when persisting.
Sourcepub fn repair_interrupted_turn(&mut self) -> Result<RepairReport, SessionError>
pub fn repair_interrupted_turn(&mut self) -> Result<RepairReport, SessionError>
Repairs an interrupted turn at the leaf (D-REPAIR). Call once, under write ownership, before the session is used; appends only, never rewrites or truncates:
- a torn last line (non-empty, not valid JSON) is terminated with
"\n"so it stays a permanently skipped line — appended before any closer, so a closer never concatenates onto the fragment; - every
toolCallof the trailing assistant message without a matchingtoolResultin the trailing run is closed with an unknown-outcome error toolResult; - one
RESUME_REPAIR_TYPErecord and async()follow when anything was repaired.
Repair is idempotent: after the first repair the trailing run is balanced and the dangling scan finds nothing. In-memory sessions and sessions whose file was never created have nothing to repair and are left untouched.
§Errors
I/O when reading or appending (fail-closed: the caller must not use the session).
Source§impl SessionManager
impl SessionManager
Sourcepub fn create(
cwd: &Path,
session_dir: &Path,
opts: CreateOptions,
) -> Result<Self, SessionError>
pub fn create( cwd: &Path, session_dir: &Path, opts: CreateOptions, ) -> Result<Self, SessionError>
New persisted session for cwd (file created on the first user/assistant message).
§Errors
SessionError::InvalidSessionId for a bad explicit id.
Sourcepub fn open(
path: &Path,
session_dir: &Path,
cwd_override: Option<&Path>,
) -> Result<Self, SessionError>
pub fn open( path: &Path, session_dir: &Path, cwd_override: Option<&Path>, ) -> Result<Self, SessionError>
Opens a session file: migrates v1/v2 in place and pre-v1 Oino files to the v3 layout; a missing file starts a new session at that path.
§Errors
I/O, SessionError::UnsupportedVersion, SessionError::MissingHeader (non-empty
file without header), SessionError::MissingCwd.
Sourcepub fn continue_recent(
cwd: &Path,
session_dir: &Path,
) -> Result<Self, SessionError>
pub fn continue_recent( cwd: &Path, session_dir: &Path, ) -> Result<Self, SessionError>
Opens the newest session of cwd, else creates one.
§Errors
Sourcepub fn in_memory(
cwd: &Path,
opts: CreateOptions,
entries: Vec<SessionEntry>,
) -> Self
pub fn in_memory( cwd: &Path, opts: CreateOptions, entries: Vec<SessionEntry>, ) -> Self
In-memory session (never written). entries are appended after a fresh header; an
invalid explicit id is replaced by a generated one.
Sourcepub fn fork_from(
source: &Path,
target_cwd: &Path,
session_dir: &Path,
opts: CreateOptions,
) -> Result<Self, SessionError>
pub fn fork_from( source: &Path, target_cwd: &Path, session_dir: &Path, opts: CreateOptions, ) -> Result<Self, SessionError>
Copies all entries of source into a new session for target_cwd with
parentSession = source. Written immediately.
§Errors
I/O, invalid source (SessionError::MissingHeader), invalid id.
Sourcepub fn find_by_id(
cwd: &Path,
id: &str,
session_dir: &Path,
) -> Result<Option<PathBuf>, SessionError>
pub fn find_by_id( cwd: &Path, id: &str, session_dir: &Path, ) -> Result<Option<PathBuf>, SessionError>
Finds a session by id: exact header id, then a unique prefix (≥ 4 chars) in the cwd directory, then over all directories.
§Errors
Sourcepub fn list(
cwd: &Path,
session_dir: &Path,
progress: Option<&dyn ProgressSink>,
cancel: Option<&AtomicBool>,
) -> Result<Vec<SessionInfo>, SessionError>
pub fn list( cwd: &Path, session_dir: &Path, progress: Option<&dyn ProgressSink>, cancel: Option<&AtomicBool>, ) -> Result<Vec<SessionInfo>, SessionError>
Sourcepub fn list_all(
session_dir: &Path,
progress: Option<&dyn ProgressSink>,
cancel: Option<&AtomicBool>,
) -> Result<Vec<SessionInfo>, SessionError>
pub fn list_all( session_dir: &Path, progress: Option<&dyn ProgressSink>, cancel: Option<&AtomicBool>, ) -> Result<Vec<SessionInfo>, SessionError>
Sourcepub fn find_most_recent(
cwd: &Path,
session_dir: &Path,
) -> Result<Option<PathBuf>, SessionError>
pub fn find_most_recent( cwd: &Path, session_dir: &Path, ) -> Result<Option<PathBuf>, SessionError>
Sourcepub fn migrate_legacy_dir(
sessions_root: &Path,
) -> Result<Vec<MigratedSession>, SessionError>
pub fn migrate_legacy_dir( sessions_root: &Path, ) -> Result<Vec<MigratedSession>, SessionError>
Migrates every pre-v1 *.jsonl directly in sessions_root (D21).
§Errors
The first I/O error; files migrated before it stay migrated.
Sourcepub fn new_session(&mut self, opts: CreateOptions) -> Result<(), SessionError>
pub fn new_session(&mut self, opts: CreateOptions) -> Result<(), SessionError>
Sourcepub fn set_session_file(&mut self, path: &Path) -> Result<(), SessionError>
pub fn set_session_file(&mut self, path: &Path) -> Result<(), SessionError>
Binds to path: loads it when it exists, otherwise starts a new
session that will be written there.
§Errors
Sourcepub const fn is_persisted(&self) -> bool
pub const fn is_persisted(&self) -> bool
Whether this manager writes to disk (isPersisted: false for in-memory).
Sourcepub const fn is_flushed(&self) -> bool
pub const fn is_flushed(&self) -> bool
Whether the file has been created (header + buffered entries written).
Sourcepub fn session_dir(&self) -> &Path
pub fn session_dir(&self) -> &Path
Sessions root.
Sourcepub fn uses_default_session_dir(&self) -> bool
pub fn uses_default_session_dir(&self) -> bool
Whether the sessions root is <default agent dir>/sessions.
Sourcepub fn session_id(&self) -> &str
pub fn session_id(&self) -> &str
Session id.
Sourcepub fn session_file(&self) -> Option<&Path>
pub fn session_file(&self) -> Option<&Path>
Session file path (planned path before the first flush).
Sourcepub const fn header(&self) -> &SessionHeader
pub const fn header(&self) -> &SessionHeader
Header.
Sourcepub fn entry_count(&self) -> usize
pub fn entry_count(&self) -> usize
Number of distinct entry ids.
Sourcepub const fn index(&self) -> &EntryIndex
pub const fn index(&self) -> &EntryIndex
The pure entry index (for the free functions in crate::context).
Sourcepub fn sync(&mut self) -> Result<(), SessionError>
pub fn sync(&mut self) -> Result<(), SessionError>
Flush + fsync the session file. Also fsyncs the parent directory until the current
file’s creation is known durable (POSIX). Fail-closed durability barrier (D-FLUSH):
callers treat SessionError::Io as “do not proceed”.
A session whose first flush never succeeded (for example an unwritable directory) retries it here, so the error surfaces at the barrier instead of being silently retried forever. In-memory sessions and sessions with nothing written yet succeed without touching the file system.
§Errors
SessionError::Io when the file cannot be opened for append, fsynced, or its
first flush retried.
Sourcepub fn append_entry(&mut self, kind: EntryKind) -> Result<EntryId, SessionError>
pub fn append_entry(&mut self, kind: EntryKind) -> Result<EntryId, SessionError>
Sourcepub fn append_message(
&mut self,
message: AgentMessage,
) -> Result<EntryId, SessionError>
pub fn append_message( &mut self, message: AgentMessage, ) -> Result<EntryId, SessionError>
Appends a message; summary roles are rejected (use compaction/branch entries).
§Errors
Sourcepub fn append_thinking_level_change(
&mut self,
level: &str,
) -> Result<EntryId, SessionError>
pub fn append_thinking_level_change( &mut self, level: &str, ) -> Result<EntryId, SessionError>
Sourcepub fn append_model_change(
&mut self,
provider: &str,
model_id: &str,
) -> Result<EntryId, SessionError>
pub fn append_model_change( &mut self, provider: &str, model_id: &str, ) -> Result<EntryId, SessionError>
Sourcepub fn append_usage(
&mut self,
kind: &str,
provider: &str,
model: &str,
usage: Usage,
note: Option<String>,
) -> Result<EntryId, SessionError>
pub fn append_usage( &mut self, kind: &str, provider: &str, model: &str, usage: Usage, note: Option<String>, ) -> Result<EntryId, SessionError>
Sourcepub fn append_compaction(
&mut self,
draft: CompactionDraft,
) -> Result<EntryId, SessionError>
pub fn append_compaction( &mut self, draft: CompactionDraft, ) -> Result<EntryId, SessionError>
Appends a compaction. Without an explicit checkpoint the current projection’s system state is stored, stamped with the entry time.
§Errors
I/O.
Sourcepub fn append_custom_entry(
&mut self,
custom_type: &str,
data: Option<JsonValue>,
) -> Result<EntryId, SessionError>
pub fn append_custom_entry( &mut self, custom_type: &str, data: Option<JsonValue>, ) -> Result<EntryId, SessionError>
Sourcepub fn append_session_info(
&mut self,
name: Option<&str>,
) -> Result<EntryId, SessionError>
pub fn append_session_info( &mut self, name: Option<&str>, ) -> Result<EntryId, SessionError>
Sourcepub fn append_custom_message_entry(
&mut self,
custom_type: &str,
content: UserContentField,
display: bool,
details: Option<JsonValue>,
) -> Result<EntryId, SessionError>
pub fn append_custom_message_entry( &mut self, custom_type: &str, content: UserContentField, display: bool, details: Option<JsonValue>, ) -> Result<EntryId, SessionError>
Sourcepub fn append_context_edit(
&mut self,
target: &EntryId,
replacement: Option<EditableContent>,
) -> Result<EntryId, SessionError>
pub fn append_context_edit( &mut self, target: &EntryId, replacement: Option<EditableContent>, ) -> Result<EntryId, SessionError>
Appends a context_edit of an editable entry on the active branch; string replacements
of assistant/toolResult targets are normalised to one text block.
§Errors
SessionError::UnknownEntry, SessionError::InvalidAppend, I/O.
Sourcepub fn append_label_change(
&mut self,
target: &EntryId,
label: Option<&str>,
) -> Result<EntryId, SessionError>
pub fn append_label_change( &mut self, target: &EntryId, label: Option<&str>, ) -> Result<EntryId, SessionError>
Sourcepub fn session_name(&self) -> Option<String>
pub fn session_name(&self) -> Option<String>
Latest session_info name in file order (trimmed; empty ⇒ None).
Sourcepub const fn leaf_id(&self) -> Option<&EntryId>
pub const fn leaf_id(&self) -> Option<&EntryId>
Current leaf id (None after SessionManager::reset_leaf or when empty).
Sourcepub fn leaf_entry(&self) -> Option<&SessionEntry>
pub fn leaf_entry(&self) -> Option<&SessionEntry>
Current leaf entry.
Sourcepub fn entry(&self, id: &EntryId) -> Option<&SessionEntry>
pub fn entry(&self, id: &EntryId) -> Option<&SessionEntry>
Entry by id.
Sourcepub fn children(&self, parent: Option<&EntryId>) -> Vec<&SessionEntry>
pub fn children(&self, parent: Option<&EntryId>) -> Vec<&SessionEntry>
Entries whose parent is parent (None ⇒ roots), file order.
Sourcepub fn branch(&self, from: Option<&EntryId>) -> Vec<&SessionEntry>
pub fn branch(&self, from: Option<&EntryId>) -> Vec<&SessionEntry>
Root → from (default leaf), all entry types; unknown id ⇒ empty.
Sourcepub fn entries(&self) -> &[SessionEntry]
pub fn entries(&self) -> &[SessionEntry]
All entries in file order.
Sourcepub fn tree(&self) -> Vec<SessionTreeNode>
pub fn tree(&self) -> Vec<SessionTreeNode>
Tree of all entries (roots and orphans in file order, children by timestamp).
Sourcepub fn build_context_entries(&self) -> Vec<SessionEntry>
pub fn build_context_entries(&self) -> Vec<SessionEntry>
Builds context entries at the leaf.
Sourcepub fn build_session_projection(&self) -> SessionProjection
pub fn build_session_projection(&self) -> SessionProjection
Builds the session projection at the leaf.
Sourcepub fn build_session_context(&self) -> SessionContext
pub fn build_session_context(&self) -> SessionContext
Builds the session context at the leaf.
Sourcepub fn reset_leaf(&mut self)
pub fn reset_leaf(&mut self)
Clears the leaf; the next entry becomes a new root.
Sourcepub fn branch_with_summary(
&mut self,
from: Option<&EntryId>,
summary: BranchSummaryDraft,
) -> Result<EntryId, SessionError>
pub fn branch_with_summary( &mut self, from: Option<&EntryId>, summary: BranchSummaryDraft, ) -> Result<EntryId, SessionError>
Moves the leaf to from (None ⇒ new root) and appends a branch_summary there.
§Errors
Sourcepub fn create_branched_session(
&self,
leaf: &EntryId,
) -> Result<PathBuf, SessionError>
pub fn create_branched_session( &self, leaf: &EntryId, ) -> Result<PathBuf, SessionError>
Writes a new session file containing the path root → leaf (/clone), with
parentSession = this file. self is unchanged.
§Errors
SessionError::UnknownEntry, SessionError::InvalidAppend for in-memory
sessions (use SessionManager::branch_into_new_session), I/O.
Sourcepub fn branch_into_new_session(
&mut self,
leaf: &EntryId,
) -> Result<Option<PathBuf>, SessionError>
pub fn branch_into_new_session( &mut self, leaf: &EntryId, ) -> Result<Option<PathBuf>, SessionError>
Branched-session semantics: replaces self with the branched session (the
file is written only if it contains a user/assistant message). Returns the new path
for persisted sessions.