Skip to main content

SessionWriter

Struct SessionWriter 

Source
pub struct SessionWriter { /* private fields */ }
Expand description

Writer for appending messages to a JSONL session file.

Opens (or creates) a .jsonl file in append mode and writes one JSON object per line. A companion .meta.json file tracks session metadata and is updated on finish().

Implementations§

Source§

impl SessionWriter

Source

pub fn create( workspace: &Path, goal: &str, model: &str, provider: &str, ) -> Result<Self>

Create a new session in the given workspace directory.

The session directory is <workspace>/.recursive/sessions/<workspace-slug>/<session-id>/. The .jsonl file and .meta.json are placed inside that directory.

Equivalent to create_with_tools(workspace, goal, model, provider, &[]); no tool_registry_hash is stamped in the meta. Prefer create_with_tools whenever the caller has a ToolRegistry, so that recursive resume (g151) can detect tool drift.

Source

pub fn create_with_tools( workspace: &Path, goal: &str, model: &str, provider: &str, tool_specs: &[ToolSpec], preset: Option<&str>, ) -> Result<Self>

Create a new session, stamping a BLAKE3 hash of tool_specs into .meta.json as tool_registry_hash. The hash is what recursive resume validates against the current registry — if they differ, resume aborts (g151).

Pass &[] for tool_specs if the caller has no registry (e.g. tests, ad-hoc tools), in which case the hash is None and resume will warn but not abort.

preset is the resolved provider preset id (e.g. “deepseek”) from the active Config. Pass None for pre-preset-config callers or when the user did not opt in; the field is Option<String> and skip_serializing_if = "Option::is_none" keeps the on-disk format clean.

Source

pub fn open_existing(session_dir: &Path) -> Result<Self>

Re-open an existing session directory for appending.

Reads the existing .meta.json to recover message_count, created_at, goal, model, and provider. The tool_registry_hash is not re-validated here — the caller (typically the Cmd::Resume handler) must have done that already.

Acquires SessionLock::acquire(session_dir) so a second resume on the same session is refused while this writer is alive.

Continues the msg_NNN sequence from where the existing transcript left off (so the first append() after open_existing does not collide with prior messages).

Source

pub fn append( &mut self, msg: &Message, parent_uuid_override: Option<&str>, usage: Option<&UsageMeta>, ) -> Result<String>

Append a message to the JSONL file.

Returns the UUID assigned to this message entry. Bumps SessionMeta.updated_at on every assistant or user message (skipping per-tool-result writes is an optimisation — a turn with N tool calls would otherwise rewrite the meta file 2N times). The “most-recent” shortcut in recursive resume (g151) relies on updated_at being live for crashed sessions.

parent_uuid_override — if Some, this UUID is used as parent_uuid for the new entry instead of self.last_uuid. Use this for subagent messages that branch off a specific parent agent message (g155).

usage — token usage to attach to this entry (non-None for assistant messages, g156).

Source

pub fn append_with_audit( &mut self, msg: &Message, audit: Option<AuditMeta>, parent_uuid_override: Option<&str>, usage: Option<&UsageMeta>, ) -> Result<String>

Append a message with optional audit metadata (Goal 153). audit should only be Some for Role::Tool messages.

Source

pub fn write_compact_boundary( &mut self, turn: u32, compacted_count: usize, summary_uuid: Option<&str>, ) -> Result<()>

Write a compact_boundary system entry directly to the JSONL (g157).

Called by SessionPersistenceSink when it receives a AgentEvent::CompactionBoundary event. The entry is written outside the normal append flow so it does not increment message_count or advance the UUID chain.

Source

pub fn finish(&mut self, status: &str) -> Result<()>

Finalise the session: flush the writer and update the meta file with the final message count, status, prompts, and cumulative cost.

Source

pub fn set_name(&mut self, name: impl Into<String>)

Set an optional human-readable display name for this session. The name is persisted to .meta.json on the next finish() call.

Source

pub fn session_id(&self) -> &str

Return the session ID.

Source

pub fn session_dir(&self) -> &Path

Return the session directory path.

Source

pub fn message_count(&self) -> u64

Return the number of messages written so far.

Source

pub fn last_uuid(&self) -> Option<&str>

Return the UUID of the last appended message (g155).

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more