Skip to main content

starweaver_runtime/output/
policy.rs

1use std::sync::Arc;
2
3use starweaver_model::OutputMode;
4
5use super::{OutputFunction, OutputSchema, OutputValidator};
6
7/// Shared reference to an output function.
8pub type DynOutputFunction = Arc<dyn OutputFunction>;
9
10/// Decomposed output policy fields.
11pub type OutputPolicyParts = (
12    Option<OutputSchema>,
13    Vec<Arc<dyn OutputValidator>>,
14    Vec<DynOutputFunction>,
15    Option<usize>,
16    Option<OutputMode>,
17    Option<bool>,
18    Option<bool>,
19);
20
21/// Complete output behavior for one agent.
22#[derive(Clone, Default)]
23pub struct OutputPolicy {
24    schema: Option<OutputSchema>,
25    validators: Vec<Arc<dyn OutputValidator>>,
26    functions: Vec<DynOutputFunction>,
27    retries: Option<usize>,
28    mode: Option<OutputMode>,
29    allow_text_output: Option<bool>,
30    allow_image_output: Option<bool>,
31}
32
33impl OutputPolicy {
34    /// Create an empty output policy.
35    #[must_use]
36    pub fn new() -> Self {
37        Self::default()
38    }
39
40    /// Create a policy with a structured output schema.
41    #[must_use]
42    pub fn structured(schema: OutputSchema) -> Self {
43        Self::new().with_schema(schema)
44    }
45
46    /// Create a structured output policy from a Rust type.
47    #[must_use]
48    pub fn typed<T>() -> Self
49    where
50        T: schemars::JsonSchema,
51    {
52        Self::structured(OutputSchema::typed::<T>())
53    }
54
55    /// Create a named structured output policy from a Rust type.
56    #[must_use]
57    pub fn typed_named<T>(name: impl Into<String>) -> Self
58    where
59        T: schemars::JsonSchema,
60    {
61        Self::structured(OutputSchema::typed_named::<T>(name))
62    }
63
64    /// Create a plain text output policy.
65    #[must_use]
66    pub fn text() -> Self {
67        Self::new().with_mode(OutputMode::Text)
68    }
69
70    /// Create an auto-selected structured output policy.
71    #[must_use]
72    pub fn auto(schema: OutputSchema) -> Self {
73        Self::structured(schema).with_mode(OutputMode::Auto)
74    }
75
76    /// Create a provider-native JSON schema output policy.
77    #[must_use]
78    pub fn native_json_schema(schema: OutputSchema) -> Self {
79        Self::structured(schema).with_mode(OutputMode::NativeJsonSchema)
80    }
81
82    /// Create a provider-native JSON object output policy.
83    #[must_use]
84    pub fn native_json_object(schema: OutputSchema) -> Self {
85        Self::structured(schema).with_mode(OutputMode::NativeJsonObject)
86    }
87
88    /// Create a tool-call structured output policy.
89    #[must_use]
90    pub fn tool(schema: OutputSchema) -> Self {
91        Self::structured(schema).with_mode(OutputMode::Tool)
92    }
93
94    /// Create a tool-call structured output policy with text fallback.
95    #[must_use]
96    pub fn tool_or_text(schema: OutputSchema) -> Self {
97        Self::structured(schema)
98            .with_mode(OutputMode::ToolOrText)
99            .allow_text_output(true)
100    }
101
102    /// Create a prompted structured output policy.
103    #[must_use]
104    pub fn prompted(schema: OutputSchema) -> Self {
105        Self::structured(schema).with_mode(OutputMode::Prompted)
106    }
107
108    /// Create an image output policy.
109    #[must_use]
110    pub fn image() -> Self {
111        Self::new()
112            .with_mode(OutputMode::Image)
113            .allow_image_output(true)
114            .allow_text_output(false)
115    }
116
117    /// Attach a structured output schema.
118    #[must_use]
119    pub fn with_schema(mut self, schema: OutputSchema) -> Self {
120        self.schema = Some(schema);
121        self
122    }
123
124    /// Select output mode for request preparation.
125    #[must_use]
126    pub const fn with_mode(mut self, mode: OutputMode) -> Self {
127        self.mode = Some(mode);
128        self
129    }
130
131    /// Configure whether text output is allowed.
132    #[must_use]
133    pub const fn allow_text_output(mut self, allow: bool) -> Self {
134        self.allow_text_output = Some(allow);
135        self
136    }
137
138    /// Configure whether image output is allowed.
139    #[must_use]
140    pub const fn allow_image_output(mut self, allow: bool) -> Self {
141        self.allow_image_output = Some(allow);
142        self
143    }
144
145    /// Attach a validator.
146    #[must_use]
147    pub fn with_validator(mut self, validator: Arc<dyn OutputValidator>) -> Self {
148        self.validators.push(validator);
149        self
150    }
151
152    /// Attach an output function.
153    #[must_use]
154    pub fn with_function(mut self, function: DynOutputFunction) -> Self {
155        self.functions.push(function);
156        self
157    }
158
159    /// Set output retry budget.
160    #[must_use]
161    pub const fn with_retries(mut self, retries: usize) -> Self {
162        self.retries = Some(retries);
163        self
164    }
165
166    /// Return configured schema.
167    #[must_use]
168    pub const fn schema(&self) -> Option<&OutputSchema> {
169        self.schema.as_ref()
170    }
171
172    /// Return configured validators.
173    #[must_use]
174    pub fn validators(&self) -> &[Arc<dyn OutputValidator>] {
175        &self.validators
176    }
177
178    /// Return configured output functions.
179    #[must_use]
180    pub fn functions(&self) -> &[DynOutputFunction] {
181        &self.functions
182    }
183
184    /// Return configured retry budget.
185    #[must_use]
186    pub const fn retries(&self) -> Option<usize> {
187        self.retries
188    }
189
190    /// Return configured output mode.
191    #[must_use]
192    pub const fn mode(&self) -> Option<OutputMode> {
193        self.mode
194    }
195
196    /// Return configured text-output allowance.
197    #[must_use]
198    pub const fn text_output_allowed(&self) -> Option<bool> {
199        self.allow_text_output
200    }
201
202    /// Return configured image-output allowance.
203    #[must_use]
204    pub const fn image_output_allowed(&self) -> Option<bool> {
205        self.allow_image_output
206    }
207
208    pub(crate) fn into_parts(self) -> OutputPolicyParts {
209        (
210            self.schema,
211            self.validators,
212            self.functions,
213            self.retries,
214            self.mode,
215            self.allow_text_output,
216            self.allow_image_output,
217        )
218    }
219}