systemprompt_models/execution/step/
content.rs1use serde::{Deserialize, Serialize};
7use systemprompt_identifiers::SkillId;
8
9use super::enums::StepType;
10
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
12pub struct PlannedTool {
13 pub tool_name: String,
14 pub arguments: serde_json::Value,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
19#[serde(tag = "type", rename_all = "snake_case")]
20pub enum StepContent {
21 Understanding,
22 Planning {
23 #[serde(skip_serializing_if = "Option::is_none")]
24 reasoning: Option<String>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 planned_tools: Option<Vec<PlannedTool>>,
27 },
28 SkillUsage {
29 skill_id: SkillId,
30 skill_name: String,
31 },
32 ToolExecution {
33 tool_name: String,
34 tool_arguments: serde_json::Value,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 tool_result: Option<serde_json::Value>,
39 },
40 Completion,
41}
42
43impl StepContent {
44 #[must_use]
45 pub const fn understanding() -> Self {
46 Self::Understanding
47 }
48
49 #[must_use]
50 pub const fn planning(
51 reasoning: Option<String>,
52 planned_tools: Option<Vec<PlannedTool>>,
53 ) -> Self {
54 Self::Planning {
55 reasoning,
56 planned_tools,
57 }
58 }
59
60 pub fn skill_usage(skill_id: SkillId, skill_name: impl Into<String>) -> Self {
61 Self::SkillUsage {
62 skill_id,
63 skill_name: skill_name.into(),
64 }
65 }
66
67 pub fn tool_execution(tool_name: impl Into<String>, tool_arguments: serde_json::Value) -> Self {
69 Self::ToolExecution {
70 tool_name: tool_name.into(),
71 tool_arguments,
72 tool_result: None,
73 }
74 }
75
76 #[must_use]
77 pub const fn completion() -> Self {
78 Self::Completion
79 }
80
81 #[must_use]
82 pub const fn step_type(&self) -> StepType {
83 match self {
84 Self::Understanding => StepType::Understanding,
85 Self::Planning { .. } => StepType::Planning,
86 Self::SkillUsage { .. } => StepType::SkillUsage,
87 Self::ToolExecution { .. } => StepType::ToolExecution,
88 Self::Completion => StepType::Completion,
89 }
90 }
91
92 #[must_use]
93 pub fn title(&self) -> String {
94 match self {
95 Self::Understanding => "Analyzing request...".to_owned(),
96 Self::Planning { .. } => "Planning response...".to_owned(),
97 Self::SkillUsage { skill_name, .. } => format!("Using {skill_name} skill..."),
98 Self::ToolExecution { tool_name, .. } => format!("Running {tool_name}..."),
99 Self::Completion => "Complete".to_owned(),
100 }
101 }
102
103 #[must_use]
104 pub const fn is_instant(&self) -> bool {
105 !matches!(self, Self::ToolExecution { .. })
106 }
107
108 #[must_use]
109 pub fn tool_name(&self) -> Option<&str> {
110 match self {
111 Self::ToolExecution { tool_name, .. } => Some(tool_name),
112 Self::SkillUsage { skill_name, .. } => Some(skill_name),
113 Self::Understanding | Self::Planning { .. } | Self::Completion => None,
114 }
115 }
116
117 #[must_use]
118 pub const fn tool_arguments(&self) -> Option<&serde_json::Value> {
120 match self {
121 Self::ToolExecution { tool_arguments, .. } => Some(tool_arguments),
122 Self::Understanding
123 | Self::Planning { .. }
124 | Self::SkillUsage { .. }
125 | Self::Completion => None,
126 }
127 }
128
129 #[must_use]
130 pub const fn tool_result(&self) -> Option<&serde_json::Value> {
132 match self {
133 Self::ToolExecution { tool_result, .. } => tool_result.as_ref(),
134 Self::Understanding
135 | Self::Planning { .. }
136 | Self::SkillUsage { .. }
137 | Self::Completion => None,
138 }
139 }
140
141 #[must_use]
142 pub fn reasoning(&self) -> Option<&str> {
143 match self {
144 Self::Planning { reasoning, .. } => reasoning.as_deref(),
145 Self::Understanding
146 | Self::SkillUsage { .. }
147 | Self::ToolExecution { .. }
148 | Self::Completion => None,
149 }
150 }
151
152 #[must_use]
153 pub fn planned_tools(&self) -> Option<&[PlannedTool]> {
154 match self {
155 Self::Planning { planned_tools, .. } => planned_tools.as_deref(),
156 Self::Understanding
157 | Self::SkillUsage { .. }
158 | Self::ToolExecution { .. }
159 | Self::Completion => None,
160 }
161 }
162
163 #[must_use]
164 pub fn with_tool_result(self, result: serde_json::Value) -> Self {
166 match self {
167 Self::ToolExecution {
168 tool_name,
169 tool_arguments,
170 ..
171 } => Self::ToolExecution {
172 tool_name,
173 tool_arguments,
174 tool_result: Some(result),
175 },
176 other @ (Self::Understanding
177 | Self::Planning { .. }
178 | Self::SkillUsage { .. }
179 | Self::Completion) => other,
180 }
181 }
182}