返回 DeepSeek-TUI-2026
task.rs
根目录 / crates / tui / src / commands / task.rs
1 //! Task commands: add/list/show/cancel
2
3 use crate::tui::app::{App, AppAction};
4
5 use super::CommandResult;
6
7 pub fn task(_app: &mut App, args: Option<&str>) -> CommandResult {
8 let raw = args.unwrap_or("").trim();
9 if raw.is_empty() || raw.eq_ignore_ascii_case("list") {
10 return CommandResult::action(AppAction::TaskList);
11 }
12
13 let mut parts = raw.splitn(2, char::is_whitespace);
14 let action = parts.next().unwrap_or("").to_ascii_lowercase();
15 let remainder = parts.next().map(str::trim).filter(|s| !s.is_empty());
16
17 match action.as_str() {
18 "add" => {
19 let Some(prompt) = remainder else {
20 return CommandResult::error("Usage: /task add <prompt>");
21 };
22 CommandResult::action(AppAction::TaskAdd {
23 prompt: prompt.to_string(),
24 })
25 }
26 "list" => CommandResult::action(AppAction::TaskList),
27 "show" => {
28 let Some(id) = remainder else {
29 return CommandResult::error("Usage: /task show <id>");
30 };
31 CommandResult::action(AppAction::TaskShow { id: id.to_string() })
32 }
33 "cancel" | "stop" => {
34 let Some(id) = remainder else {
35 return CommandResult::error("Usage: /task cancel <id>");
36 };
37 CommandResult::action(AppAction::TaskCancel { id: id.to_string() })
38 }
39 _ => CommandResult::error("Usage: /task [add <prompt>|list|show <id>|cancel <id>]"),
40 }
41 }
42
43 #[cfg(test)]
44 mod tests {
45 use super::*;
46 use crate::config::Config;
47 use crate::tui::app::TuiOptions;
48 use std::path::PathBuf;
49
50 fn app() -> App {
51 App::new(
52 TuiOptions {
53 model: "deepseek-v4-pro".to_string(),
54 workspace: PathBuf::from("."),
55 config_path: None,
56 config_profile: None,
57 allow_shell: false,
58 use_alt_screen: false,
59 use_mouse_capture: false,
60 use_bracketed_paste: true,
61 max_subagents: 2,
62 skills_dir: PathBuf::from("."),
63 memory_path: PathBuf::from("memory.md"),
64 notes_path: PathBuf::from("notes.txt"),
65 mcp_config_path: PathBuf::from("mcp.json"),
66 use_memory: false,
67 start_in_agent_mode: false,
68 skip_onboarding: true,
69 yolo: false,
70 resume_session_id: None,
71 initial_input: None,
72 },
73 &Config::default(),
74 )
75 }
76
77 #[test]
78 fn parses_add_and_cancel() {
79 let mut app = app();
80 let add = task(&mut app, Some("add write tests"));
81 assert!(matches!(
82 add.action,
83 Some(AppAction::TaskAdd { prompt }) if prompt == "write tests"
84 ));
85
86 let cancel = task(&mut app, Some("cancel task_1234"));
87 assert!(matches!(
88 cancel.action,
89 Some(AppAction::TaskCancel { id }) if id == "task_1234"
90 ));
91 }
92
93 #[test]
94 fn validates_usage() {
95 let mut app = app();
96 let result = task(&mut app, Some("add"));
97 assert!(result.message.is_some());
98 assert!(result.action.is_none());
99 }
100 }
101
101 lines RUST