codetether_agent/tool/session_task/
tool.rs1use super::handlers::{clear_goal, list, reaffirm, set_goal, task_add, task_status};
4use super::params::Params;
5use crate::session::tasks::TaskLog;
6use crate::tool::{Tool, ToolResult};
7use anyhow::{Result, anyhow};
8use async_trait::async_trait;
9use serde_json::{Value, json};
10
11pub struct SessionTaskTool;
12
13impl Default for SessionTaskTool {
14 fn default() -> Self {
15 Self
16 }
17}
18
19impl SessionTaskTool {
20 pub fn new() -> Self {
21 Self
22 }
23}
24
25#[async_trait]
26impl Tool for SessionTaskTool {
27 fn id(&self) -> &str {
28 "session_task"
29 }
30 fn name(&self) -> &str {
31 "Session Task & Goal"
32 }
33 fn description(&self) -> &str {
34 "Manage the session's goal and task list. Actions: \
35 `set_goal` (objective, success_criteria?, forbidden?), \
36 `reaffirm` (progress_note), \
37 `clear_goal` (reason?), \
38 `task_add` (content, id?, parent_id?), \
39 `task_status` (id, status: pending|in_progress|done|blocked|cancelled, note?), \
40 `list`. Events are appended to the session's .tasks.jsonl."
41 }
42 fn parameters(&self) -> Value {
43 json!({
44 "type": "object",
45 "properties": {
46 "action": {"type": "string", "enum": [
47 "set_goal", "reaffirm", "clear_goal",
48 "task_add", "task_status", "list"
49 ]},
50 "objective": {"type": "string"},
51 "success_criteria": {"type": "array", "items": {"type": "string"}},
52 "forbidden": {"type": "array", "items": {"type": "string"}},
53 "progress_note": {"type": "string"},
54 "reason": {"type": "string"},
55 "id": {"type": "string"},
56 "content": {"type": "string"},
57 "parent_id": {"type": "string"},
58 "status": {"type": "string",
59 "enum": ["pending", "in_progress", "done", "blocked", "cancelled"]},
60 "note": {"type": "string"}
61 },
62 "required": ["action"]
63 })
64 }
65
66 async fn execute(&self, params: Value) -> Result<ToolResult> {
67 let p: Params = serde_json::from_value(params)?;
68 let sid = p
69 .ct_session_id
70 .clone()
71 .or_else(|| std::env::var("CODETETHER_SESSION_ID").ok())
72 .ok_or_else(|| anyhow!("session id not available; cannot locate task log"))?;
73 let log = TaskLog::for_session(&sid)?;
74 match p.action.as_str() {
75 "set_goal" => set_goal(&log, p).await,
76 "reaffirm" => reaffirm(&log, p).await,
77 "clear_goal" => clear_goal(&log, p).await,
78 "task_add" => task_add(&log, p).await,
79 "task_status" => task_status(&log, p).await,
80 "list" => list(&log).await,
81 other => Ok(ToolResult::error(format!("unknown action: {other}"))),
82 }
83 }
84}