feat: implement interactive lesson management and update command handling

This commit is contained in:
asepharyana
2026-07-13 02:53:30 +07:00
parent ab8b098a57
commit dc0f1c7647
10 changed files with 288 additions and 209 deletions
+1 -4
View File
@@ -23,10 +23,7 @@ Slash commands:
/help Show this help
/quit Quit session
/mode <name> Switch mode (chat, bash, workflow)
/lesson <text> Create a lesson
/lesson list List lessons
/lesson export Export lessons
/lesson import Import lessons
/lesson Interactive lesson manager
/clear Clear transcript";
/// Route an incoming action while the help overlay is open.
+70
View File
@@ -0,0 +1,70 @@
use crate::app::state::rest::AppStateRest;
/// A unified representation of a lesson item for the interactive TUI overlay.
#[derive(Debug, Clone)]
pub enum LearningItem {
Pending {
name: String,
content: String,
scope: String,
confidence: String,
},
Stored {
name: String,
content: String,
lifecycle: String,
scope: String,
description: String,
},
}
/// Dynamically read all pending and stored lessons.
pub fn get_learning_items(state: &AppStateRest) -> Vec<LearningItem> {
let mut items = Vec::new();
// 1. Load pending lessons from session directory
let pending = if let Some(ref rt) = state.session_runtime {
crate::app::review::load_pending_lessons(&rt.session_dir)
} else {
Vec::new()
};
for p in pending {
let scope_str = match p.lesson.scope {
crate::app::review::LessonScope::Project => "project",
crate::app::review::LessonScope::Global => "global",
}.to_string();
let conf_str = match p.lesson.confidence {
crate::app::review::Confidence::Human => "human",
crate::app::review::Confidence::Verified => "verified",
crate::app::review::Confidence::Unverified => "unverified",
crate::app::review::Confidence::Auto => "auto",
}.to_string();
items.push(LearningItem::Pending {
name: p.lesson.name,
content: p.lesson.content,
scope: scope_str,
confidence: conf_str,
});
}
// 2. Load stored memory lessons from long-term memory directory
let names = crate::model::memory::Memory::list(&state.memory_dir);
for name in names {
if let Ok(mem) = crate::model::memory::Memory::read(&state.memory_dir, &name) {
if mem.kind == "lesson" {
items.push(LearningItem::Stored {
name: mem.name,
content: mem.content,
lifecycle: mem.lifecycle,
scope: mem.scope.unwrap_or_else(|| "project".to_string()),
description: mem.description,
});
}
}
}
items
}
+1 -22
View File
@@ -1,8 +1,6 @@
//! TUI mode definitions and per-mode input/action handlers, one submodule
//! per overlay/mode (bash, editor, effort, mcp, quit confirm, rewind, etc.).
use serde::{Deserialize, Serialize};
pub mod bash;
pub mod editor;
pub mod effort;
@@ -14,23 +12,4 @@ pub mod quit_confirm;
pub mod rewind;
pub mod settings;
pub mod todo;
/// Which input/overlay mode the TUI is currently in; drives both key
/// routing (`controller/input.rs`) and rendering.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ModeKind {
Chat,
Bash,
Workflow,
Help,
Settings,
QuitConfirm,
KeyInput,
Editor,
Effort,
Mcp,
Todo,
Rewind,
Loading,
}
pub mod learning;