feat(tui): implement agent turn engine for background processing and enhance input handling
This commit is contained in:
@@ -418,7 +418,7 @@ pub enum Overlay {
|
||||
Effort,
|
||||
/// MCP server management panel.
|
||||
Mcp,
|
||||
/// TODO list overlay.
|
||||
/// Task list overlay.
|
||||
Todo,
|
||||
/// Session rewind / history scrubber.
|
||||
Rewind,
|
||||
@@ -541,7 +541,7 @@ impl Default for MiscState {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// EditorState (simplified — used by the Editor overlay)
|
||||
// EditorState — used by the Editor overlay
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Simple inline editor state for the TUI.
|
||||
@@ -668,10 +668,17 @@ pub fn current_effort(state: &AppStateRest) -> usize {
|
||||
}
|
||||
|
||||
/// Cycle effort level up or down.
|
||||
pub fn cycle_effort(state: &mut AppStateRest, _forward: bool) {
|
||||
// Simplified: cycle through levels
|
||||
pub fn cycle_effort(state: &mut AppStateRest, forward: bool) {
|
||||
let n = EFFORT_LEVELS.len();
|
||||
state.misc.effort_level = (state.misc.effort_level % n) + 1;
|
||||
if forward {
|
||||
state.misc.effort_level = (state.misc.effort_level % n) + 1;
|
||||
} else {
|
||||
state.misc.effort_level = if state.misc.effort_level <= 1 {
|
||||
n
|
||||
} else {
|
||||
state.misc.effort_level - 1
|
||||
};
|
||||
}
|
||||
state.mark_dirty();
|
||||
}
|
||||
|
||||
@@ -699,9 +706,37 @@ pub enum LearningItem {
|
||||
},
|
||||
}
|
||||
|
||||
/// Return learning items from state (simplified — uses session_runtime data).
|
||||
pub fn get_learning_items(_state: &AppStateRest) -> Vec<LearningItem> {
|
||||
Vec::new()
|
||||
/// Return learning items from state.
|
||||
///
|
||||
/// Reads lesson markdown files from the `lessons/` subdirectory
|
||||
/// under the memory directory.
|
||||
pub fn get_learning_items(state: &AppStateRest) -> Vec<LearningItem> {
|
||||
let lessons_dir = state.memory_dir.join("lessons");
|
||||
if !lessons_dir.exists() {
|
||||
return Vec::new();
|
||||
}
|
||||
let mut items = Vec::new();
|
||||
if let Ok(entries) = std::fs::read_dir(&lessons_dir) {
|
||||
for entry in entries.flatten() {
|
||||
let path = entry.path();
|
||||
if path.extension().and_then(|e| e.to_str()) == Some("md") {
|
||||
if let Ok(content) = std::fs::read_to_string(&path) {
|
||||
items.push(LearningItem::Stored {
|
||||
name: path
|
||||
.file_stem()
|
||||
.unwrap_or_default()
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
content,
|
||||
lifecycle: "filesystem".to_string(),
|
||||
scope: "filesystem".to_string(),
|
||||
description: String::new(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
items
|
||||
}
|
||||
|
||||
/// Cycle the selected index within bounds.
|
||||
@@ -726,15 +761,23 @@ pub fn rewind_count(state: &AppStateRest) -> usize {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Context window helpers (stubs for status bar)
|
||||
// Context window helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Resolve the window size for context window management.
|
||||
///
|
||||
/// Uses the model name from settings to determine max context window,
|
||||
/// falling back to settings-configured max or 128k default.
|
||||
pub fn resolve_context_window(
|
||||
_app_config: &zesdex_domain::cms::AppConfig,
|
||||
_settings: &zesdex_domain::cms::Settings,
|
||||
settings: &zesdex_domain::cms::Settings,
|
||||
) -> usize {
|
||||
// Default to 128k for most modern models
|
||||
// Use configured max tokens from settings, or default to 128k
|
||||
if let Some(max) = settings.max_tokens {
|
||||
if max > 0 {
|
||||
return max as usize;
|
||||
}
|
||||
}
|
||||
128_000
|
||||
}
|
||||
|
||||
@@ -836,6 +879,34 @@ pub const DEFAULT_HELP_TEXT: &str = r#" Zesdex TUI — Keyboard Shortcuts
|
||||
Esc Dismiss editor
|
||||
"#;
|
||||
|
||||
impl Default for AppStateRest {
|
||||
fn default() -> Self {
|
||||
AppStateRest {
|
||||
settings: Settings::default(),
|
||||
app_config: AppConfig::default(),
|
||||
workspace_roots: Vec::new(),
|
||||
session_id: String::new(),
|
||||
session_dir: PathBuf::new(),
|
||||
memory_dir: PathBuf::new(),
|
||||
worktrees_dir: PathBuf::new(),
|
||||
dir_cache: Arc::new(tokio::sync::RwLock::new(DirCache::new())),
|
||||
mention_index: MentionIndex::new(),
|
||||
session_runtime: None,
|
||||
transcript_cache: TranscriptCache::new(200),
|
||||
scroll: ScrollState::new(),
|
||||
input: InputState::new(),
|
||||
misc: MiscState::new(),
|
||||
turn_events: Arc::new(Mutex::new(VecDeque::new())),
|
||||
turn_in_flight_flag: Arc::new(Mutex::new(false)),
|
||||
abort_flag: Arc::new(AtomicBool::new(false)),
|
||||
workflow_engine: SimpleWorkflowEngine::new(),
|
||||
dirty: true,
|
||||
quit: false,
|
||||
help_text: DEFAULT_HELP_TEXT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AppStateRest {
|
||||
/// Construct initial TUI state.
|
||||
pub fn new(
|
||||
|
||||
Reference in New Issue
Block a user