DeepSeek TUI Session State Management: A Complete Guide to Turn-Based Conversation
TLDR: DeepSeek TUI maintains conversation state through a centralized Session struct that persists for the entire TUI lifetime, managing turn-based message flow, context compaction via cycles, and project-aware file tracking while enforcing safety controls over tool execution.
DeepSeek TUI is a Rust-based terminal interface for interacting with DeepSeek language models. At its core lies a robust session state management system that enables persistent, turn-based conversations with automatic context compaction and tool execution capabilities. The repository Hmbown/DeepSeek-TUI implements this architecture through a centralized Session object defined in [crates/tui/src/core/session.rs](https://github.com/Hmbown/DeepSeek-TUI/blob/main/crates/tui/src/core/session.rs).
The Session Struct: Central State Container
The Session struct encapsulates the entire conversation state and configuration. Created when the TUI starts or when the dispatcher launches new execution, it persists until the session terminates.
Key fields include:
model– The identifier string (e.g.,deepseek-v4-flash) specifying which LLM to query.messages– AVec<Message>storing the raw OpenAI-compatible chat history where every turn appends new entries.reasoning_effort– Optional tier (off,low,medium,high,max) controlling DeepSeek's "thinking" mode depth.workspace– The rootPathBuffor resolving all relative file operations during tool execution.system_promptandcompaction_summary_prompt– System-level prompts prepended to requests, with the latter storing compacted conversation summaries.total_usage– Cumulative token counters (SessionUsage) updated after each turn viaSessionUsage::add.cycle_count,current_cycle_started, andcycle_briefings– Turn-based bookkeeping for conversation segmentation and the/cyclescommand.allow_shell,trust_mode,auto_approve– Boolean flags controlling shell tool invocation, workspace boundary trust, and automatic safety approval.working_set– A repo-aware file cache rebuilt from messages on demand, enabling the/filesand/searchcommands.project_context– Information loaded fromAGENTS.mdandCLAUDE.mdfiles for context-aware tooling.id– A UUID for telemetry and debugging purposes.
Turn-Based Conversation Lifecycle
Each interaction follows a strict turn-based execution model defined in [crates/tui/src/core/engine.rs](https://github.com/Hmbown/DeepSeek-TUI/blob/main/crates/tui/src/core/engine.rs). The lifecycle proceeds through five distinct phases:
1. User Input Capture
The UI creates a Message::User variant and calls Session::add_message to append the user content to the session history.
2. Engine Execution
The core engine reads session.messages, constructs the LLM request, transmits it to the DeepSeek API, and receives the response. The engine handles ContentBlock::Thinking segments by repeating reasoning blocks before final answers to comply with DeepSeek's "thinking mode" requirements.
3. Tool Call Processing
If the assistant response includes tool calls (e.g., fetch_url, web_search, apply_patch), the engine executes the appropriate handlers. Results are appended as Message::Tool entries, and the turn may replay until the model produces a final answer without tool requests.
4. Context Compaction and Cycle Handling
When the token budget approaches limits or after a configurable number of turns, the engine triggers compaction via Session::compaction_summary_prompt. The current conversation summarizes into a brief system prompt, cycle_count increments, and a CycleBriefing stores the phase summary. This bounds session size and enables the /cycles command timeline.
5. Working Set Reconstruction
Session::rebuild_working_set synchronizes the repo-aware file cache with the latest messages, ensuring subsequent /files and /search commands reference only conversation-relevant paths.
Cycle Management and Context Compaction
Long-running sessions utilize cycles to prevent unbounded token growth. A cycle represents a logical conversation segment capped by compaction events.
The CycleBriefing type, defined in [crates/tui/src/rlm/turn.rs](https://github.com/Hmbown/DeepSeek-TUI/blob/main/crates/tui/src/rlm/turn.rs), stores summaries of approximately 3,000 tokens maximum. When compaction triggers:
- The engine generates a summary of the current conversation context.
- The summary populates
compaction_summary_prompt. cycle_countincrements andcurrent_cycle_startedupdates.- A new
CycleBriefingentry appends tocycle_briefings.
This design ensures the session remains serializable to disk for later resumption while maintaining manageable context windows.
Working Set and Project Awareness
The WorkingSet struct, implemented in [crates/tui/src/core/working_set.rs](https://github.com/Hmbown/DeepSeek-TUI/blob/main/crates/tui/src/core/working_set.rs), maintains a cache of files the model may reference during the conversation. Rather than scanning the entire repository each turn, the working set rebuilds incrementally from message content via rebuild_working_set.
This enables efficient "search-and-open" functionality without filesystem overhead, while project_context fields load metadata from AGENTS.md and CLAUDE.md files to provide contextual awareness of project conventions.
Safety Controls and Session Configuration
The session enforces security boundaries through three critical flags stored as struct fields:
allow_shell– Controls whether the model may invoke shell execution tools.trust_mode– Determines if paths outside theworkspaceroot are trusted for file operations.auto_approve– When disabled, requires manual user confirmation before executing safety-sensitive actions.
These controls, alongside token accounting via SessionUsage, provide fine-grained governance over autonomous tool execution.
Practical Implementation Example
The following Rust code demonstrates session initialization and turn processing patterns:
// Creating a new session (called from the dispatcher)
let session = Session::new(
"deepseek-v4-flash".to_string(),
PathBuf::from("./my_project"),
/*allow_shell=*/ false,
/*trust_mode=*/ false,
PathBuf::from("./notes.md"),
PathBuf::from("./mcp_config.toml"),
);
// Adding a user message
session.add_message(Message::User {
role: "user".into(),
content: "Explain the Rust ownership model".into(),
});
// Run a turn – this is done by the engine; simplified here
let response = engine::run_turn(&mut session)?;
// The response is added back to the session
session.add_message(response);
// After many turns, compact the context to keep the session small
if session.total_usage.output_tokens > 10_000 {
let summary = engine::compact_context(&session)?;
session.compaction_summary_prompt = Some(summary);
}
Summary
- The
Sessionstruct incrates/tui/src/core/session.rsserves as the single source of truth for conversation state, configuration, and safety controls. - Turn-based processing follows a five-phase lifecycle: user input → engine execution → tool handling → compaction → working set rebuild.
- Cycles prevent context explosion by summarizing conversation segments into compact briefings stored in
cycle_briefings. - The WorkingSet provides repo-aware file caching without full repository scans.
- Safety flags (
allow_shell,trust_mode,auto_approve) enforce execution boundaries whileSessionUsagetracks cumulative token consumption. - All message history persists in OpenAI-compatible format, enabling serialization and session resumption.
Frequently Asked Questions
How does DeepSeek TUI handle session persistence?
The Session struct maintains all conversation state in serializable fields (messages, cycle_briefings, total_usage) that can be written to disk. The implementation stores raw message history and compaction summaries, allowing users to save and resume sessions later without losing context. The UUID field (id) aids in telemetry correlation across resumed sessions.
What triggers context compaction in a session?
Compaction triggers when total_usage.output_tokens exceeds configurable thresholds (e.g., 10,000 tokens) or after a set number of turns. The engine in crates/tui/src/core/engine.rs invokes compact_context, generating a summary that becomes the new compaction_summary_prompt. This increments cycle_count and creates a CycleBriefing entry to maintain conversation continuity while bounding memory usage.
How are tool calls integrated into the turn-based flow?
When the LLM returns tool calls, the engine executes the corresponding tools (defined in the tool registry) and appends results as Message::Tool variants to session.messages. The turn replays with the tool results included until the model provides a final assistant response without additional tool requests. This cycle may iterate multiple times per user turn depending on tool dependencies.
What is the working set and when does it rebuild?
The WorkingSet is a repo-aware cache of files referenced in the conversation, implemented in crates/tui/src/core/working_set.rs. It rebuilds via rebuild_working_set after each turn completion, scanning session.messages for file references. This enables the /files and /search commands to surface relevant project files without scanning the entire repository filesystem on every interaction.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →