Skip to main content

ic_rig/
message.rs

1//! Core message types shared across all providers.
2//!
3//! A [`Message`] represents a single turn in a conversation. Providers are
4//! responsible for converting these generic types into their API-specific format
5//! via `From`/`TryFrom`.
6
7use serde::{Deserialize, Serialize};
8
9// ── Content primitives ────────────────────────────────────────────────────────
10
11/// Plain text content.
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13pub struct Text {
14    pub text: String,
15}
16
17impl From<&str> for Text {
18    fn from(s: &str) -> Self {
19        Self { text: s.to_owned() }
20    }
21}
22
23impl From<String> for Text {
24    fn from(s: String) -> Self {
25        Self { text: s }
26    }
27}
28
29/// A tool invocation requested by the model.
30#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
31pub struct ToolCall {
32    /// Provider-assigned identifier for this call (used to correlate results).
33    pub id: String,
34    /// Name of the tool to call.
35    pub name: String,
36    /// JSON-encoded arguments for the tool.
37    pub arguments: serde_json::Value,
38}
39
40/// The result of executing a tool, sent back to the model.
41#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
42pub struct ToolResult {
43    /// Must match the [`ToolCall::id`] this result answers.
44    pub call_id: String,
45    /// Tool name (some providers require this in addition to the id).
46    pub name: String,
47    /// The serialised output returned by the tool.
48    pub content: String,
49}
50
51// ── User content ──────────────────────────────────────────────────────────────
52
53/// Content that can appear in a user-turn message.
54#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
55#[serde(tag = "type", rename_all = "snake_case")]
56pub enum UserContent {
57    /// A text message from the user.
58    Text(Text),
59    /// The result of a previous tool call.
60    ToolResult(ToolResult),
61}
62
63impl From<&str> for UserContent {
64    fn from(s: &str) -> Self {
65        UserContent::Text(s.into())
66    }
67}
68
69impl From<String> for UserContent {
70    fn from(s: String) -> Self {
71        UserContent::Text(s.into())
72    }
73}
74
75impl From<ToolResult> for UserContent {
76    fn from(r: ToolResult) -> Self {
77        UserContent::ToolResult(r)
78    }
79}
80
81// ── Assistant content ─────────────────────────────────────────────────────────
82
83/// Content that can appear in an assistant-turn message.
84#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
85#[serde(tag = "type", rename_all = "snake_case")]
86pub enum AssistantContent {
87    /// A text reply from the model.
88    Text(Text),
89    /// A tool call issued by the model.
90    ToolCall(ToolCall),
91}
92
93// ── Message ───────────────────────────────────────────────────────────────────
94
95/// A single turn in a conversation.
96#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
97#[serde(tag = "role", rename_all = "lowercase")]
98pub enum Message {
99    /// Instruction context prepended before the conversation (system prompt).
100    System { content: String },
101    /// Input from the human side of the conversation.
102    User { content: Vec<UserContent> },
103    /// Output from the model.
104    Assistant { content: Vec<AssistantContent> },
105}
106
107impl Message {
108    /// Convenience constructor for a plain text user message.
109    pub fn user(text: impl Into<String>) -> Self {
110        Message::User {
111            content: vec![UserContent::Text(Text { text: text.into() })],
112        }
113    }
114
115    /// Convenience constructor for a plain text assistant message.
116    pub fn assistant(text: impl Into<String>) -> Self {
117        Message::Assistant {
118            content: vec![AssistantContent::Text(Text { text: text.into() })],
119        }
120    }
121
122    /// Convenience constructor for a system message.
123    pub fn system(text: impl Into<String>) -> Self {
124        Message::System { content: text.into() }
125    }
126}