Expand description
Thread / Session split (issue #5261).
codewhale’s Session was really a thread. The new split is:
Thread— durable, persisted, owns the append-onlyJournaland theleafIdcursor. One row instate.threads, one directory on disk.Session— ephemeral, per-turn / per-engine-lifetime, owns the in-memoryTurnContextplus the live approval/sandbox posture for thisSessionId. Many sessions can attach to one thread over time, but only oneSessiondrives a turn for a givenThreadIdat a time.
The thread manager (ThreadManager in crate::lib) already can start a
session with no TUI attached (spawn_thread_with_history); this file
formalizes the types that make that first-class and moves the former
crates/tui/src/core/session.rs state (model, reasoning_effort,
AppendLog, PrefixStabilityManager, frozen_prefix,
messages_revision) into crates/core so both TUI and headless share it.
Structs§
- Session
- Ephemeral session within a thread (one engine lifetime / one turn’s
live posture). The TUI’s
EngineHandleand the headlessexecboth hold aSessionthat points at the sameThreadIdbut with differentSessionIds. - Thread
- Durable thread (the former
Session). One per conversation, persisted instate.threads. The only new field vs the oldSessionisleaf_id— the journal cursor — plus the typedThreadId. All other fields keep their persisted JSON shape unchanged.
Functions§
- session_
for_ thread - Split helper: derive a
Sessionfrom an existingThreadwithout cloning the journal. Headless and TUI call the same constructor so the request shape stays identical.