Skip to main content

systemprompt_models/wire/canonical/request/
content.rs

1//! Message roles and content parts of a canonical request.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use serde_json::Value;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum Role {
10    System,
11    User,
12    Assistant,
13    Tool,
14}
15
16impl Role {
17    pub const fn as_str(self) -> &'static str {
18        match self {
19            Self::System => "system",
20            Self::User => "user",
21            Self::Assistant => "assistant",
22            Self::Tool => "tool",
23        }
24    }
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum ImageDetail {
29    Auto,
30    Low,
31    High,
32}
33
34impl ImageDetail {
35    pub const fn as_str(self) -> &'static str {
36        match self {
37            Self::Auto => "auto",
38            Self::Low => "low",
39            Self::High => "high",
40        }
41    }
42}
43
44#[derive(Debug, Clone)]
45pub enum ImageSource {
46    Base64 {
47        media_type: String,
48        data: String,
49        detail: Option<ImageDetail>,
50    },
51    Url {
52        url: String,
53        detail: Option<ImageDetail>,
54    },
55}
56
57#[derive(Debug, Clone)]
58pub enum CanonicalContent {
59    Text(String),
60    Image(ImageSource),
61    ToolUse {
62        id: String,
63        name: String,
64        // JSON: MCP tool-call arguments are the tool's own JSON object.
65        input: Value,
66        // Why: Gemini requires function-call `thoughtSignature` values replayed verbatim.
67        signature: Option<String>,
68    },
69    ToolResult {
70        tool_use_id: String,
71        content: Vec<Self>,
72        is_error: bool,
73        structured_content: Option<Value>,
74        // JSON: MCP `_meta` is an open map of vendor-prefixed keys.
75        meta: Option<Value>,
76    },
77    Thinking {
78        text: String,
79        signature: Option<String>,
80        // Why: OpenAI Responses requires the reasoning item ID and encrypted content
81        // replayed verbatim for stateless reasoning continuity.
82        id: Option<String>,
83        encrypted_content: Option<String>,
84    },
85}
86
87#[derive(Debug, Clone)]
88pub struct CanonicalMessage {
89    pub role: Role,
90    pub content: Vec<CanonicalContent>,
91}