wauldo/client/
reasoning.rs1use serde_json::json;
4
5use crate::error::{Error, Result};
6use crate::types::*;
7
8use super::AgentClient;
9
10impl AgentClient {
11 pub async fn reason(&mut self, problem: &str) -> Result<ReasoningResult> {
29 self.reason_with_options(problem, ReasoningOptions::default())
30 .await
31 }
32
33 pub async fn reason_with_options(
35 &mut self,
36 problem: &str,
37 options: ReasoningOptions,
38 ) -> Result<ReasoningResult> {
39 if problem.trim().is_empty() {
40 return Err(Error::validation_field(
41 "Problem cannot be empty",
42 "problem",
43 ));
44 }
45
46 let depth = options.depth.unwrap_or(3);
47 let branches = options.branches.unwrap_or(3);
48
49 if !(1..=10).contains(&depth) {
50 return Err(Error::validation_field(
51 "Depth must be between 1 and 10",
52 "depth",
53 ));
54 }
55 if !(1..=10).contains(&branches) {
56 return Err(Error::validation_field(
57 "Branches must be between 1 and 10",
58 "branches",
59 ));
60 }
61
62 let content = self
63 .call_tool(
64 "reason_tree_of_thought",
65 json!({
66 "problem": problem,
67 "depth": depth,
68 "branches": branches
69 }),
70 )
71 .await?;
72
73 Ok(self.parse_reasoning_result(&content, problem, depth, branches))
74 }
75
76 pub(crate) fn parse_reasoning_result(
77 &self,
78 content: &str,
79 problem: &str,
80 depth: usize,
81 branches: usize,
82 ) -> ReasoningResult {
83 if let Ok(data) = serde_json::from_str::<serde_json::Value>(content) {
85 if let Some(solution) = data.get("solution").and_then(|s| s.as_str()) {
86 return ReasoningResult {
87 problem: data["problem"].as_str().unwrap_or(problem).to_string(),
88 solution: solution.to_string(),
89 thought_tree: data["thought_tree"].as_str().unwrap_or(content).to_string(),
90 depth: data["depth"].as_u64().unwrap_or(depth as u64) as usize,
91 branches: data["branches"].as_u64().unwrap_or(branches as u64) as usize,
92 raw_content: content.to_string(),
93 };
94 }
95 }
96
97 let mut solution = String::new();
99 let mut in_solution = false;
100
101 for line in content.lines() {
102 if line.contains("Solution:") || line.contains("Best path:") {
103 in_solution = true;
104 continue;
105 }
106 if in_solution && !line.trim().is_empty() {
107 solution = line.trim().to_string();
108 break;
109 }
110 }
111
112 ReasoningResult {
113 problem: problem.to_string(),
114 solution: if solution.is_empty() {
115 "See thought tree for analysis".to_string()
116 } else {
117 solution
118 },
119 thought_tree: content.to_string(),
120 depth,
121 branches,
122 raw_content: content.to_string(),
123 }
124 }
125}