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