feat: add 'todofinish' tool to mark tasks as completed in the todo list; update system prompts for task execution
This commit is contained in:
@@ -158,6 +158,7 @@ pub fn all_tools() -> Vec<Box<dyn Tool>> {
|
||||
Box::new(super::tool::utility::dir_cache_update::DirCacheUpdate),
|
||||
Box::new(super::tool::utility::pong::Pong),
|
||||
Box::new(super::tool::utility::todowrite::Todowrite),
|
||||
Box::new(super::tool::utility::todofinish::Todofinish),
|
||||
Box::new(super::tool::lsp::LspConnect),
|
||||
Box::new(super::tool::lsp::LspDiagnostics),
|
||||
Box::new(super::tool::lsp::LspHover),
|
||||
|
||||
@@ -5,3 +5,4 @@ pub mod dir_cache_update;
|
||||
pub mod dir_list;
|
||||
pub mod pong;
|
||||
pub mod todowrite;
|
||||
pub mod todofinish;
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
//! Tool for marking tasks as finished in the session's todo list.
|
||||
|
||||
use serde_json::{json, Value};
|
||||
use anyhow::{Result, anyhow};
|
||||
use std::path::PathBuf;
|
||||
use super::super::{Tool, ToolCtx};
|
||||
|
||||
/// Tool that marks tasks as finished in the session's todo.md.
|
||||
pub struct Todofinish;
|
||||
|
||||
impl Tool for Todofinish {
|
||||
fn name(&self) -> &'static str {
|
||||
"todofinish"
|
||||
}
|
||||
|
||||
fn description(&self) -> &'static str {
|
||||
"Mark tasks as finished in the session todo list (todo.md). You can mark all tasks as finished by leaving the 'task_index' empty, or specify a 1-based index to finish a specific task."
|
||||
}
|
||||
|
||||
fn parameters(&self) -> Value {
|
||||
json!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"task_index": {
|
||||
"type": "integer",
|
||||
"description": "Optional 1-based index of the task to mark as finished. If omitted, ALL unfinished tasks will be marked as finished."
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn run(&self, ctx: &ToolCtx, args: &Value) -> Result<String> {
|
||||
let path: PathBuf = ctx.session_dir.join("todo.md");
|
||||
if !path.exists() {
|
||||
return Ok("No todo.md found in session directory. Nothing to finish.".to_string());
|
||||
}
|
||||
|
||||
let content = std::fs::read_to_string(&path)
|
||||
.map_err(|e| anyhow!("failed to read todo.md: {}", e))?;
|
||||
|
||||
let task_index = args.get("task_index").and_then(|v| v.as_i64());
|
||||
|
||||
let mut new_content = String::new();
|
||||
let mut task_count = 0;
|
||||
let mut modified = false;
|
||||
|
||||
for line in content.lines() {
|
||||
if line.trim_start().starts_with("- [ ]") {
|
||||
task_count += 1;
|
||||
if let Some(target) = task_index {
|
||||
if task_count == target {
|
||||
new_content.push_str(&line.replacen("- [ ]", "- [x]", 1));
|
||||
modified = true;
|
||||
} else {
|
||||
new_content.push_str(line);
|
||||
}
|
||||
} else {
|
||||
// Mark all as finished
|
||||
new_content.push_str(&line.replacen("- [ ]", "- [x]", 1));
|
||||
modified = true;
|
||||
}
|
||||
} else {
|
||||
new_content.push_str(line);
|
||||
}
|
||||
new_content.push('\n');
|
||||
}
|
||||
|
||||
if !modified {
|
||||
return Ok("No unfinished tasks found or index out of bounds.".to_string());
|
||||
}
|
||||
|
||||
std::fs::write(&path, new_content)
|
||||
.map_err(|e| anyhow!("failed to write to todo.md: {}", e))?;
|
||||
|
||||
if let Some(idx) = task_index {
|
||||
Ok(format!("Successfully marked task {} as finished.", idx))
|
||||
} else {
|
||||
Ok("Successfully marked ALL tasks as finished.".to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user