gemini_adk_rs/planners/
built_in.rs1use async_trait::async_trait;
7
8use super::{Planner, PlannerError};
9use crate::llm::LlmRequest;
10
11#[derive(Debug, Clone, Default)]
16pub struct BuiltInPlanner {
17 custom_instruction: Option<String>,
19}
20
21impl BuiltInPlanner {
22 pub fn new() -> Self {
24 Self::default()
25 }
26
27 pub fn with_instruction(instruction: impl Into<String>) -> Self {
29 Self {
30 custom_instruction: Some(instruction.into()),
31 }
32 }
33}
34
35const DEFAULT_PLANNING_INSTRUCTION: &str = "\
36Before taking any action, think step by step about what you need to do. \
37Create a brief plan, then execute it. If you need to adjust your plan based \
38on new information, explain your reasoning before changing course.";
39
40#[async_trait]
41impl Planner for BuiltInPlanner {
42 fn build_planning_instruction(
43 &self,
44 _request: &LlmRequest,
45 ) -> Result<Option<String>, PlannerError> {
46 Ok(Some(self.custom_instruction.clone().unwrap_or_else(|| {
47 DEFAULT_PLANNING_INSTRUCTION.to_string()
48 })))
49 }
50
51 fn process_planning_response(
52 &self,
53 _response_text: &str,
54 ) -> Result<Option<String>, PlannerError> {
55 Ok(None)
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn default_instruction() {
66 let planner = BuiltInPlanner::new();
67 let request = LlmRequest::default();
68 let instruction = planner.build_planning_instruction(&request).unwrap();
69 assert!(instruction.is_some());
70 assert!(instruction.unwrap().contains("step by step"));
71 }
72
73 #[test]
74 fn custom_instruction() {
75 let planner = BuiltInPlanner::with_instruction("Plan carefully");
76 let request = LlmRequest::default();
77 let instruction = planner.build_planning_instruction(&request).unwrap();
78 assert_eq!(instruction.unwrap(), "Plan carefully");
79 }
80
81 #[test]
82 fn response_passthrough() {
83 let planner = BuiltInPlanner::new();
84 let result = planner.process_planning_response("some response").unwrap();
85 assert!(result.is_none());
86 }
87}