Bug Description
The DeepSeek provider defines Message::User.content as a plain String:
// providers/deepseek.rs line 190-193
User {
content: String,
name: Option<String>,
},
Because of this, when a rig message::Message::User contains multiple UserContent items (e.g. user text + timestamp, or text + image description), the TryFrom<message::Message> conversion splits them into separate Message::User entries:
// Each text item becomes its own Message::User
let text_messages = content.into_iter()
.filter_map(|content| match content {
message::UserContent::Text(text) => Some(Message::User {
content: text.text,
name: None,
}),
_ => None,
}).collect::<Vec<_>>();
This changes the semantics of the conversation — what was a single user turn becomes multiple turns in the API request.
Expected Behavior
DeepSeek API supports array-format content (same as OpenAI):
{
"role": "user",
"content": [
{"type": "text", "text": "first part"},
{"type": "text", "text": "second part"}
]
}
The OpenAI provider already handles this correctly with OneOrMany<UserContent>:
// providers/openai/completion/mod.rs line 143-151
User {
#[serde(
deserialize_with = "string_or_one_or_many",
serialize_with = "serialize_user_content"
)]
content: OneOrMany<UserContent>,
name: Option<String>,
},
The DeepSeek provider should do the same — use OneOrMany<UserContent> (or equivalent) so multiple content items stay in a single message instead of being split.
Example
Input rig message:
RigMessage::User {
content: OneOrMany::many(vec![
UserContent::text("搜索一下有没有人吐槽skill没用"),
UserContent::text("2026-02-25 21:10"),
])
}
Current output (wrong — split into 2 messages):
[
{"role": "user", "content": "搜索一下有没有人吐槽skill没用"},
{"role": "user", "content": "2026-02-25 21:10"}
]
Expected output (single message, array content):
[
{
"role": "user",
"content": [
{"type": "text", "text": "搜索一下有没有人吐槽skill没用"},
{"type": "text", "text": "2026-02-25 21:10"}
]
}
]
Environment
Bug Description
The DeepSeek provider defines
Message::User.contentas a plainString:Because of this, when a rig
message::Message::Usercontains multipleUserContentitems (e.g. user text + timestamp, or text + image description), theTryFrom<message::Message>conversion splits them into separateMessage::Userentries:This changes the semantics of the conversation — what was a single user turn becomes multiple turns in the API request.
Expected Behavior
DeepSeek API supports array-format content (same as OpenAI):
{ "role": "user", "content": [ {"type": "text", "text": "first part"}, {"type": "text", "text": "second part"} ] }The OpenAI provider already handles this correctly with
OneOrMany<UserContent>:The DeepSeek provider should do the same — use
OneOrMany<UserContent>(or equivalent) so multiple content items stay in a single message instead of being split.Example
Input rig message:
Current output (wrong — split into 2 messages):
[ {"role": "user", "content": "搜索一下有没有人吐槽skill没用"}, {"role": "user", "content": "2026-02-25 21:10"} ]Expected output (single message, array content):
[ { "role": "user", "content": [ {"type": "text", "text": "搜索一下有没有人吐槽skill没用"}, {"type": "text", "text": "2026-02-25 21:10"} ] } ]Environment