1use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct AgentTask {
23 pub objective: String,
25 pub expected_output: Option<String>,
27 pub allowed_tools: Vec<String>,
29}
30
31impl AgentTask {
32 pub fn new(objective: impl Into<String>) -> Self {
34 Self {
35 objective: objective.into(),
36 expected_output: None,
37 allowed_tools: Vec::new(),
38 }
39 }
40
41 pub fn with_expected_output(mut self, expected_output: impl Into<String>) -> Self {
43 self.expected_output = Some(expected_output.into());
44 self
45 }
46
47 pub fn with_allowed_tools(
49 mut self,
50 tools: impl IntoIterator<Item = impl Into<String>>,
51 ) -> Self {
52 self.allowed_tools = tools.into_iter().map(Into::into).collect();
53 self
54 }
55
56 pub fn objective(&self) -> &str {
58 &self.objective
59 }
60
61 pub fn expected_output(&self) -> Option<&str> {
63 self.expected_output.as_deref()
64 }
65
66 pub fn allowed_tools(&self) -> &[String] {
68 &self.allowed_tools
69 }
70
71 pub fn is_tool_restricted(&self) -> bool {
73 !self.allowed_tools.is_empty()
74 }
75}
76
77impl From<AgentTask> for String {
79 fn from(task: AgentTask) -> Self {
80 task.objective
81 }
82}
83
84impl std::fmt::Display for AgentTask {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 write!(f, "{}", self.objective)
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_agent_task_new_has_no_constraints() {
96 let task = AgentTask::new("研究 LangChain");
97 assert_eq!(task.objective(), "研究 LangChain");
98 assert_eq!(task.expected_output(), None);
99 assert!(task.allowed_tools().is_empty());
100 assert!(!task.is_tool_restricted());
101 }
102
103 #[test]
104 fn test_agent_task_with_constraints() {
105 let task = AgentTask::new("写周报")
106 .with_expected_output("Markdown 一页")
107 .with_allowed_tools(["web_search", "calculator"]);
108 assert_eq!(task.expected_output(), Some("Markdown 一页"));
109 assert_eq!(
110 task.allowed_tools(),
111 &["web_search".to_string(), "calculator".to_string()]
112 );
113 assert!(task.is_tool_restricted());
114 assert_eq!(task.to_string(), "写周报");
115 }
116
117 #[test]
118 fn test_agent_task_from_string_loses_constraints() {
119 let task = AgentTask::new("查一下天气")
120 .with_expected_output("一句话")
121 .with_allowed_tools(["weather"]);
122 let bare: String = task.into();
123 assert_eq!(bare, "查一下天气");
124 }
125
126 #[test]
127 fn test_agent_task_serialize_roundtrip() {
128 let task = AgentTask::new("翻译")
129 .with_expected_output("中文")
130 .with_allowed_tools(["dict"]);
131 let json = serde_json::to_string(&task).unwrap();
132 let back: AgentTask = serde_json::from_str(&json).unwrap();
133 assert_eq!(back.objective(), "翻译");
134 assert_eq!(back.expected_output(), Some("中文"));
135 assert_eq!(back.allowed_tools(), &["dict".to_string()]);
136 }
137}