fleetforge_prompt/
types.rs

1use fleetforge_trust::{Trust, TrustOrigin};
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4
5/// Chat roles supported across FleetForge prompting surfaces.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "snake_case")]
8pub enum ChatRole {
9    System,
10    User,
11    Assistant,
12    Tool,
13}
14
15/// Normalised chat message for prompt compilation and runtime execution.
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct ChatMessage {
18    pub role: ChatRole,
19    #[serde(default)]
20    pub content: Value,
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub name: Option<String>,
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub tool_call_id: Option<String>,
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub metadata: Option<Value>,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub trust: Option<Trust>,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub trust_origin: Option<TrustOrigin>,
31}
32
33impl ChatMessage {
34    pub fn system<S: Into<String>>(content: S) -> Self {
35        Self {
36            role: ChatRole::System,
37            content: Value::String(content.into()),
38            name: None,
39            tool_call_id: None,
40            metadata: None,
41            trust: Some(Trust::Trusted),
42            trust_origin: None,
43        }
44    }
45
46    pub fn user<S: Into<String>>(content: S) -> Self {
47        Self {
48            role: ChatRole::User,
49            content: Value::String(content.into()),
50            name: None,
51            tool_call_id: None,
52            metadata: None,
53            trust: Some(Trust::Untrusted),
54            trust_origin: None,
55        }
56    }
57}
58
59/// Tool/function specification exposed to a language model call.
60#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct ToolSpec {
62    pub name: String,
63    pub description: String,
64    #[serde(default)]
65    pub schema: Value,
66    #[serde(skip_serializing_if = "Option::is_none")]
67    pub trust: Option<Trust>,
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub trust_origin: Option<TrustOrigin>,
70}
71
72/// Provider usage metrics returned by language model adapters.
73#[derive(Debug, Clone, Serialize, Deserialize, Default)]
74pub struct ModelUsage {
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub prompt_tokens: Option<i64>,
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub completion_tokens: Option<i64>,
79    #[serde(skip_serializing_if = "Option::is_none")]
80    pub total_tokens: Option<i64>,
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub cost: Option<f64>,
83}
84
85/// Canonical response returned from chat invocations.
86#[derive(Debug, Clone, Serialize, Deserialize, Default)]
87pub struct ModelResponse {
88    #[serde(default, skip_serializing_if = "Vec::is_empty")]
89    pub messages: Vec<ChatMessage>,
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub response_json: Option<Value>,
92    #[serde(skip_serializing_if = "Option::is_none")]
93    pub usage: Option<ModelUsage>,
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub provider: Option<String>,
96    #[serde(skip_serializing_if = "Option::is_none")]
97    pub provider_version: Option<String>,
98    #[serde(skip_serializing_if = "Option::is_none")]
99    pub raw: Option<Value>,
100}
101
102/// Result of compiling a prompt reference with variables and context.
103#[derive(Debug, Clone, Serialize, Deserialize, Default)]
104pub struct CompiledPrompt {
105    #[serde(default)]
106    pub messages: Vec<ChatMessage>,
107    #[serde(default, skip_serializing_if = "Vec::is_empty")]
108    pub tools: Vec<ToolSpec>,
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pub response_schema: Option<Value>,
111}