mofa_kernel/agent/components/
reasoner.rs1use crate::agent::capabilities::ReasoningStrategy;
6use crate::agent::context::AgentContext;
7use crate::agent::error::AgentResult;
8use crate::agent::types::AgentInput;
9use async_trait::async_trait;
10use serde::{Deserialize, Serialize};
11
12#[async_trait]
43pub trait Reasoner: Send + Sync {
44 async fn reason(&self, input: &AgentInput, ctx: &AgentContext) -> AgentResult<ReasoningResult>;
46
47 fn strategy(&self) -> ReasoningStrategy;
49
50 fn supports_multi_step(&self) -> bool {
52 matches!(
53 self.strategy(),
54 ReasoningStrategy::ReAct { .. }
55 | ReasoningStrategy::ChainOfThought
56 | ReasoningStrategy::TreeOfThought { .. }
57 )
58 }
59
60 fn name(&self) -> &str {
62 "reasoner"
63 }
64
65 fn description(&self) -> Option<&str> {
67 None
68 }
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct ReasoningResult {
74 pub thoughts: Vec<ThoughtStep>,
76 pub decision: Decision,
78 pub confidence: f32,
80}
81
82impl ReasoningResult {
83 pub fn respond(content: impl Into<String>) -> Self {
85 Self {
86 thoughts: vec![],
87 decision: Decision::Respond {
88 content: content.into(),
89 },
90 confidence: 1.0,
91 }
92 }
93
94 pub fn call_tool(tool_name: impl Into<String>, arguments: serde_json::Value) -> Self {
96 Self {
97 thoughts: vec![],
98 decision: Decision::CallTool {
99 tool_name: tool_name.into(),
100 arguments,
101 },
102 confidence: 1.0,
103 }
104 }
105
106 pub fn with_thought(mut self, step: ThoughtStep) -> Self {
108 self.thoughts.push(step);
109 self
110 }
111
112 pub fn with_confidence(mut self, confidence: f32) -> Self {
114 self.confidence = confidence.clamp(0.0, 1.0);
115 self
116 }
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct ThoughtStep {
122 pub step_type: ThoughtStepType,
124 pub content: String,
126 pub step_number: usize,
128 pub timestamp_ms: u64,
130}
131
132impl ThoughtStep {
133 pub fn new(step_type: ThoughtStepType, content: impl Into<String>, step_number: usize) -> Self {
135 let now = std::time::SystemTime::now()
136 .duration_since(std::time::UNIX_EPOCH)
137 .unwrap_or_default()
138 .as_millis() as u64;
139
140 Self {
141 step_type,
142 content: content.into(),
143 step_number,
144 timestamp_ms: now,
145 }
146 }
147
148 pub fn thought(content: impl Into<String>, step_number: usize) -> Self {
150 Self::new(ThoughtStepType::Thought, content, step_number)
151 }
152
153 pub fn analysis(content: impl Into<String>, step_number: usize) -> Self {
155 Self::new(ThoughtStepType::Analysis, content, step_number)
156 }
157
158 pub fn planning(content: impl Into<String>, step_number: usize) -> Self {
160 Self::new(ThoughtStepType::Planning, content, step_number)
161 }
162
163 pub fn reflection(content: impl Into<String>, step_number: usize) -> Self {
165 Self::new(ThoughtStepType::Reflection, content, step_number)
166 }
167}
168
169#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
171pub enum ThoughtStepType {
172 Thought,
174 Analysis,
176 Planning,
178 Reflection,
180 Evaluation,
182 Custom(String),
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
188pub enum Decision {
189 Respond {
191 content: String,
193 },
194 CallTool {
196 tool_name: String,
198 arguments: serde_json::Value,
200 },
201 CallMultipleTools {
203 tool_calls: Vec<ToolCall>,
205 },
206 Delegate {
208 agent_id: String,
210 task: String,
212 },
213 NeedMoreInfo {
215 questions: Vec<String>,
217 },
218 CannotHandle {
220 reason: String,
222 },
223}
224
225#[derive(Debug, Clone, Serialize, Deserialize)]
227pub struct ToolCall {
228 pub tool_name: String,
230 pub arguments: serde_json::Value,
232}
233
234impl ToolCall {
235 pub fn new(tool_name: impl Into<String>, arguments: serde_json::Value) -> Self {
237 Self {
238 tool_name: tool_name.into(),
239 arguments,
240 }
241 }
242}
243
244