feat: remove session hub and related commands from the application

This commit is contained in:
asepharyana
2026-07-11 22:40:45 +07:00
parent 1f182021fb
commit 93d1bbb7c1
11 changed files with 44 additions and 140 deletions
+41 -55
View File
@@ -9,6 +9,8 @@ use crate::app::state::runtime::TurnEvent;
use crate::app::state::types::{AgentMode, Origin, Overlay, Toast, ToastKind};
use crate::dto::chat::message::{ChatMessage, Role};
const MAX_TOOL_ONLY_TURNS: usize = 6;
const MAX_AGENT_STEPS: usize = 40;
#[derive(Debug, Clone)]
@@ -58,9 +60,6 @@ pub enum Action {
LessonReject {
name: String,
},
SaveSession,
ResumeSession,
RefreshSessions,
}
pub fn apply_action(state: &mut AppStateRest, action: Action) {
@@ -82,11 +81,9 @@ pub fn apply_action(state: &mut AppStateRest, action: Action) {
| ModeKind::Workflow => Overlay::None,
ModeKind::Help => Overlay::Help,
ModeKind::Settings => Overlay::Settings,
ModeKind::SessionHub => Overlay::SessionHub,
ModeKind::QuitConfirm => Overlay::QuitConfirm,
ModeKind::Onboard => Overlay::Onboard,
ModeKind::OnboardProvider => Overlay::OnboardProvider,
ModeKind::Picker => Overlay::Picker,
ModeKind::KeyInput => Overlay::KeyInput,
ModeKind::Editor => Overlay::Editor,
ModeKind::Effort => Overlay::Effort,
@@ -110,6 +107,7 @@ pub fn apply_action(state: &mut AppStateRest, action: Action) {
rt.push_message(ChatMessage::user(text));
}
spawn_turn(state);
state.push_transcript(ChatMessageDisplay::new(Role::Assistant, "Thinking...".to_string()));
state.dirty = true;
}
Action::InsertChar(c) => {
@@ -273,53 +271,6 @@ pub fn apply_action(state: &mut AppStateRest, action: Action) {
}
state.dirty = true;
}
Action::SaveSession => {
save_current_session(state);
state.push_toast(Toast::new(ToastKind::Success, "session saved".to_string()));
state.dirty = true;
}
Action::ResumeSession => {
let base = state.store_base_dir();
let sessions = crate::model::session::Session::list(&base);
let target = sessions.into_iter()
.filter(|s| s.id != state.session_id)
.max_by_key(|s| s.updated_at);
if let Some(session) = target {
let conv_path = session.conversation_path(&base);
let loaded_msgs: Vec<crate::dto::chat::message::ChatMessage> =
std::fs::read_to_string(&conv_path)
.ok()
.and_then(|data| serde_json::from_str(&data).ok())
.unwrap_or_default();
state.session_id = session.id.clone();
state.session_dir = session.session_dir(&base);
state.session_runtime = Some(crate::app::state::runtime::SessionRuntime::new(
state.session_dir.clone(),
));
state.transcript_cache.messages.clear();
if let Some(ref mut rt) = state.session_runtime {
for msg in loaded_msgs {
let display = ChatMessageDisplay::new(
msg.role.clone(),
msg.content.clone().unwrap_or_default(),
);
state.transcript_cache.messages.push(display);
rt.push_message(msg);
}
}
state.push_toast(Toast::new(ToastKind::Success,
format!("resumed session: {}", session.title)));
} else {
state.push_toast(Toast::new(ToastKind::Info,
"no other sessions to resume".to_string()));
}
state.dirty = true;
}
Action::RefreshSessions => {
let base = state.store_base_dir();
state.sessions = crate::model::session::Session::list(&base);
state.dirty = true;
}
Action::Tick => {
let now_ms = chrono::Utc::now().timestamp_millis();
state.misc.drain_expired_toasts(now_ms);
@@ -341,16 +292,39 @@ pub fn apply_action(state: &mut AppStateRest, action: Action) {
TurnEvent::AssistantMessage(msg) => {
let display_content = msg.content.clone().unwrap_or_default();
if !display_content.is_empty() {
state.push_transcript(ChatMessageDisplay::new(Role::Assistant, display_content));
let replaced = if let Some(last) = state.transcript_cache.messages.last_mut() {
if last.role == Role::Assistant && last.content == "Thinking..." {
last.content = display_content.clone();
true
} else {
false
}
} else {
false
};
if !replaced {
state.push_transcript(ChatMessageDisplay::new(Role::Assistant, display_content));
}
}
if let Some(ref mut rt) = state.session_runtime {
rt.push_message(msg);
}
}
TurnEvent::ToolResult { tool_call_id, tool_name, output, is_error } => {
TurnEvent::ToolResult { tool_call_id, tool_name, output, is_error, path } => {
let display_path = path.unwrap_or_default();
let display = if tool_name == "read" {
let line_count = output.lines().count();
if !display_path.is_empty() {
format!("read: {} ({} lines)", display_path, line_count)
} else {
format!("read: {} line(s)", line_count)
}
} else {
format!("{}: {}", tool_name, output)
};
state.push_transcript(ChatMessageDisplay::new(
Role::Tool,
format!("{}: {}", tool_name, output),
display,
));
if let Some(ref mut rt) = state.session_runtime {
rt.push_message(ChatMessage::tool_result(tool_call_id.clone(), output.clone()));
@@ -520,6 +494,7 @@ fn run_agent_turn(
) -> anyhow::Result<()> {
let mut msgs = messages.to_vec();
let mut edits_this_turn = 0u32;
let mut tool_only_rounds = 0usize;
let system_text = format!(
"{}\n\n{}",
@@ -531,6 +506,13 @@ fn run_agent_turn(
}
for _step in 0..MAX_AGENT_STEPS {
if tool_only_rounds >= MAX_TOOL_ONLY_TURNS {
msgs.push(ChatMessage::user(
"Stop calling tools. Respond naturally now.".to_string(),
));
tool_only_rounds = 0;
}
let response = tc
.client
.chat_with_tools(&msgs, Some(tc.tdefs.clone()))?;
@@ -540,6 +522,7 @@ fn run_agent_turn(
let content = response.content.clone().unwrap_or_default();
if has_tool_calls {
tool_only_rounds += 1;
let tool_calls = response.tool_calls.clone().unwrap_or_default();
msgs.push(response);
for tool_call in tool_calls {
@@ -583,6 +566,8 @@ fn run_agent_turn(
edits_this_turn += 1;
}
let tool_path = args.get("path").and_then(|v| v.as_str()).map(|s| s.to_string());
{
if let Ok(mut q) = events_q.lock() {
q.push_back(TurnEvent::ToolResult {
@@ -590,6 +575,7 @@ fn run_agent_turn(
tool_name: tool_name.clone(),
output: output.clone(),
is_error,
path: tool_path,
});
}
}