feat(tui): update system message for clarity and conciseness in tool usage instructions

This commit is contained in:
asepharyana
2026-07-20 14:47:55 +07:00
parent fe2e916937
commit 5a373d1031
10 changed files with 130 additions and 21 deletions
+8
View File
@@ -163,6 +163,14 @@ pub fn apply_action(state: &mut crate::state::AppStateRest, action: Action) {
rt.messages = msgs;
}
}
zesdex_infrastructure::TurnEvent::TodoUpdate(content) => {
state.misc.todo_content = content;
state.toast_success("TODO list updated.");
}
zesdex_infrastructure::TurnEvent::PlanUpdate(content) => {
state.misc.plan_content = content;
state.toast_success("Project plan updated.");
}
zesdex_infrastructure::TurnEvent::Done => {
state.turn_in_flight_flag.store(false, std::sync::atomic::Ordering::SeqCst);
// Mark dirty so spinner disappears
@@ -30,6 +30,8 @@ pub enum Command {
Compact,
/// `/todo` — open the todo-list overlay.
TodoOpen,
/// `/plan` — open the project plan overlay.
PlanOpen,
/// `/usage` — open the usage-stats overlay.
UsageOpen,
/// Catch-all: unrecognised or non-slash input.
@@ -82,6 +84,7 @@ pub fn parse_command(text: &str) -> Command {
"/model" => Command::ModelList,
"/compact" => Command::Compact,
"/todo" => Command::TodoOpen,
"/plan" => Command::PlanOpen,
"/usage" => Command::UsageOpen,
_ => Command::Unknown(cmd.to_string()),
};
@@ -129,6 +132,9 @@ pub fn apply_command(cmd: Command) -> Vec<crate::action::Action> {
Command::TodoOpen => {
vec![crate::action::Action::OpenOverlay(crate::state::Overlay::Todo)]
}
Command::PlanOpen => {
vec![crate::action::Action::OpenOverlay(crate::state::Overlay::Plan)]
}
Command::UsageOpen => {
vec![crate::action::Action::OpenOverlay(crate::state::Overlay::Usage)]
}
+6
View File
@@ -422,6 +422,8 @@ pub enum Overlay {
Mcp,
/// Task list overlay.
Todo,
/// Project plan overlay.
Plan,
/// Session rewind / history scrubber.
Rewind,
/// Learning / lesson management panel.
@@ -450,6 +452,7 @@ impl Overlay {
Overlay::Effort => "effort",
Overlay::Mcp => "mcp",
Overlay::Todo => "todo",
Overlay::Plan => "plan",
Overlay::Rewind => "rewind",
Overlay::Learning => "learning",
Overlay::Usage => "usage",
@@ -498,6 +501,8 @@ pub struct MiscState {
pub tick_count: u64,
/// Cached content of the TODO file.
pub todo_content: String,
/// Cached content of the PLAN file.
pub plan_content: String,
/// Whether a lesson background task is currently running.
pub lesson_running: bool,
/// Text waiting to be written to the system clipboard.
@@ -518,6 +523,7 @@ impl MiscState {
api_connected: false,
tick_count: 0,
todo_content: String::new(),
plan_content: String::new(),
lesson_running: false,
pending_clipboard_copy: None,
}
+8 -18
View File
@@ -101,24 +101,14 @@ fn run_turn(
let tools = all_tools();
let defs = tool_defs(&tools);
// Build tool description list for the system prompt
let tool_desc: Vec<String> = tools.iter().map(|t| {
let params = t.parameters();
let required = params.get("required").and_then(|r| r.as_array())
.map(|a| a.iter().filter_map(|v| v.as_str()).collect::<Vec<_>>().join(", "))
.unwrap_or_default();
format!("- {}: {} (required params: {})", t.name(), t.description(), required)
}).collect();
let tool_desc_text = tool_desc.join("\n");
// Prepend system message with tool descriptions
let sys_msg = ChatMessage::system(format!(
"You are Zesdex, an AI coding agent with access to the following tools:\n\n{}\n\n\
When using tools, always provide ALL required parameters in your tool call. \
If a tool returns an error, fix the issue before retrying. \
Respond conversationally and helpfully.",
tool_desc_text
));
// Prepend system message
let sys_msg = ChatMessage::system(
"You are Zesdex, an AI coding assistant. You have access to various tools via native function calling to help the user. \
For any non-trivial tasks, you MUST prioritize creating a structured plan (using `plan_enter`) and a list of TODOs (using `todowrite`) BEFORE executing any other tools or modifying files. \
Use other tools when necessary. If a tool returns an error, fix the issue before retrying. \
Respond conversationally, concisely, and helpfully."
.to_string(),
);
messages.insert(0, sys_msg);
let tool_ctx = ToolCtx::builder()
@@ -16,6 +16,7 @@ pub mod quit_confirm;
pub mod rewind;
pub mod settings;
pub mod todo;
pub mod plan;
pub mod usage;
use crate::state::{AppStateRest, Overlay};
@@ -95,6 +96,9 @@ pub fn render_overlay(
Overlay::Todo => {
todo::render(frame, overlay_area, block, state);
}
Overlay::Plan => {
plan::render(frame, overlay_area, block, state);
}
Overlay::Rewind => {
rewind::render(frame, overlay_area, block, state);
}
@@ -0,0 +1,32 @@
//! Overlay: Project Plan view — shows the full project plan content.
use ratatui::style::{Modifier, Style};
use ratatui::text::Span;
use ratatui::widgets::{Block, Paragraph, Wrap};
use ratatui::Frame;
use crate::view::theme::Theme;
/// Render the Project Plan overlay.
pub fn render(
frame: &mut Frame,
area: ratatui::layout::Rect,
block: Block<'static>,
state: &crate::state::AppStateRest,
) {
let block = block
.title(Span::styled(
" Project Plan ",
Style::default()
.fg(Theme::ACCENT_TEAL)
.add_modifier(Modifier::BOLD),
))
.border_style(Style::default().fg(Theme::ACCENT_TEAL));
let content = if state.misc.plan_content.is_empty() {
" No active project plan."
} else {
&state.misc.plan_content
};
let paragraph = Paragraph::new(content)
.block(block)
.wrap(Wrap { trim: false });
frame.render_widget(paragraph, area);
}