objectiveai_sdk/agent/completions/message/
user_message.rs1use super::rich_content::{RichContent, RichContentExpression};
4use crate::functions;
5use functions::expression::{
6 ExpressionError, FromStarlarkValue, WithExpression,
7};
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10use starlark::values::dict::DictRef as StarlarkDictRef;
11use starlark::values::{UnpackValue, Value as StarlarkValue};
12
13#[derive(
15 Debug,
16 Clone,
17 PartialEq,
18 Serialize,
19 Deserialize,
20 JsonSchema,
21 arbitrary::Arbitrary,
22)]
23#[schemars(rename = "agent.completions.message.UserMessage")]
24pub struct UserMessage {
25 pub content: RichContent,
27 #[serde(skip_serializing_if = "Option::is_none")]
29 #[schemars(extend("omitempty" = true))]
30 pub name: Option<String>,
31}
32
33impl UserMessage {
34 pub fn push(&mut self, other: &UserMessage) {
35 self.content.push(&other.content);
36 if self.name.is_none() {
37 self.name.clone_from(&other.name);
38 }
39 }
40
41 pub fn has_name(&self) -> bool {
42 self.name.as_ref().is_some_and(|n| !n.is_empty())
43 }
44
45 pub fn prepare(&mut self) {
47 self.content.prepare();
48 if self.name.as_ref().is_some_and(String::is_empty) {
49 self.name = None;
50 }
51 }
52
53}
54
55impl FromStarlarkValue for UserMessage {
56 fn from_starlark_value(
57 value: &StarlarkValue,
58 ) -> Result<Self, ExpressionError> {
59 let dict = StarlarkDictRef::from_value(*value).ok_or_else(|| {
60 ExpressionError::StarlarkConversionError(
61 "UserMessage: expected dict".into(),
62 )
63 })?;
64 let mut content = None;
65 let mut name = None;
66 for (k, v) in dict.iter() {
67 let key = <&str as UnpackValue>::unpack_value(k)
68 .map_err(|e| {
69 ExpressionError::StarlarkConversionError(e.to_string())
70 })?
71 .ok_or_else(|| {
72 ExpressionError::StarlarkConversionError(
73 "UserMessage: expected string key".into(),
74 )
75 })?;
76 match key {
77 "content" => {
78 content = Some(RichContent::from_starlark_value(&v)?)
79 }
80 "name" => name = Option::<String>::from_starlark_value(&v)?,
81 _ => {}
82 }
83 }
84 Ok(UserMessage {
85 content: content.ok_or_else(|| {
86 ExpressionError::StarlarkConversionError(
87 "UserMessage: missing content".into(),
88 )
89 })?,
90 name,
91 })
92 }
93}
94
95#[derive(
97 Debug,
98 Clone,
99 PartialEq,
100 Serialize,
101 Deserialize,
102 JsonSchema,
103 arbitrary::Arbitrary,
104)]
105#[schemars(rename = "agent.completions.message.UserMessageExpression")]
106pub struct UserMessageExpression {
107 pub content: functions::expression::WithExpression<RichContentExpression>,
109 #[serde(
111 default,
112 skip_serializing_if = "functions::expression::WithExpression::is_none"
113 )]
114 #[schemars(with = "Option<functions::expression::WithExpression<String>>", extend("omitempty" = true))]
115 pub name: functions::expression::WithExpression<Option<String>>,
116}
117
118impl UserMessageExpression {
119 pub fn compile(
121 self,
122 params: &functions::expression::Params,
123 ) -> Result<UserMessage, functions::expression::ExpressionError> {
124 let content = self.content.compile_one(params)?.compile(params)?;
125 let name = self.name.compile_one(params)?;
126 Ok(UserMessage { content, name })
127 }
128}
129
130impl FromStarlarkValue for UserMessageExpression {
131 fn from_starlark_value(
132 value: &StarlarkValue,
133 ) -> Result<Self, ExpressionError> {
134 let dict = StarlarkDictRef::from_value(*value).ok_or_else(|| {
135 ExpressionError::StarlarkConversionError(
136 "UserMessageExpression: expected dict".into(),
137 )
138 })?;
139 let mut content = None;
140 let mut name = WithExpression::Value(None);
141 for (k, v) in dict.iter() {
142 let key = <&str as UnpackValue>::unpack_value(k)
143 .map_err(|e| {
144 ExpressionError::StarlarkConversionError(e.to_string())
145 })?
146 .ok_or_else(|| {
147 ExpressionError::StarlarkConversionError(
148 "UserMessageExpression: expected string key".into(),
149 )
150 })?;
151 match key {
152 "content" => {
153 content = Some(WithExpression::Value(
154 RichContentExpression::from_starlark_value(&v)?,
155 ))
156 }
157 "name" => {
158 name = WithExpression::Value(if v.is_none() {
159 None
160 } else {
161 Some(String::from_starlark_value(&v)?)
162 });
163 }
164 _ => {}
165 }
166 }
167 Ok(UserMessageExpression {
168 content: content.ok_or_else(|| {
169 ExpressionError::StarlarkConversionError(
170 "UserMessageExpression: missing content".into(),
171 )
172 })?,
173 name,
174 })
175 }
176}