use std::sync::Arc;
use starweaver_model::OutputMode;
use super::{OutputFunction, OutputSchema, OutputValidator};
pub type DynOutputFunction = Arc<dyn OutputFunction>;
pub type OutputPolicyParts = (
Option<OutputSchema>,
Vec<Arc<dyn OutputValidator>>,
Vec<DynOutputFunction>,
Option<usize>,
Option<OutputMode>,
Option<bool>,
Option<bool>,
);
#[derive(Clone, Default)]
pub struct OutputPolicy {
schema: Option<OutputSchema>,
validators: Vec<Arc<dyn OutputValidator>>,
functions: Vec<DynOutputFunction>,
retries: Option<usize>,
mode: Option<OutputMode>,
allow_text_output: Option<bool>,
allow_image_output: Option<bool>,
}
impl OutputPolicy {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn structured(schema: OutputSchema) -> Self {
Self::new().with_schema(schema)
}
#[must_use]
pub fn typed<T>() -> Self
where
T: schemars::JsonSchema,
{
Self::structured(OutputSchema::typed::<T>())
}
#[must_use]
pub fn typed_named<T>(name: impl Into<String>) -> Self
where
T: schemars::JsonSchema,
{
Self::structured(OutputSchema::typed_named::<T>(name))
}
#[must_use]
pub fn text() -> Self {
Self::new().with_mode(OutputMode::Text)
}
#[must_use]
pub fn auto(schema: OutputSchema) -> Self {
Self::structured(schema).with_mode(OutputMode::Auto)
}
#[must_use]
pub fn native_json_schema(schema: OutputSchema) -> Self {
Self::structured(schema).with_mode(OutputMode::NativeJsonSchema)
}
#[must_use]
pub fn native_json_object(schema: OutputSchema) -> Self {
Self::structured(schema).with_mode(OutputMode::NativeJsonObject)
}
#[must_use]
pub fn tool(schema: OutputSchema) -> Self {
Self::structured(schema).with_mode(OutputMode::Tool)
}
#[must_use]
pub fn tool_or_text(schema: OutputSchema) -> Self {
Self::structured(schema)
.with_mode(OutputMode::ToolOrText)
.allow_text_output(true)
}
#[must_use]
pub fn prompted(schema: OutputSchema) -> Self {
Self::structured(schema).with_mode(OutputMode::Prompted)
}
#[must_use]
pub fn image() -> Self {
Self::new()
.with_mode(OutputMode::Image)
.allow_image_output(true)
.allow_text_output(false)
}
#[must_use]
pub fn with_schema(mut self, schema: OutputSchema) -> Self {
self.schema = Some(schema);
self
}
#[must_use]
pub const fn with_mode(mut self, mode: OutputMode) -> Self {
self.mode = Some(mode);
self
}
#[must_use]
pub const fn allow_text_output(mut self, allow: bool) -> Self {
self.allow_text_output = Some(allow);
self
}
#[must_use]
pub const fn allow_image_output(mut self, allow: bool) -> Self {
self.allow_image_output = Some(allow);
self
}
#[must_use]
pub fn with_validator(mut self, validator: Arc<dyn OutputValidator>) -> Self {
self.validators.push(validator);
self
}
#[must_use]
pub fn with_function(mut self, function: DynOutputFunction) -> Self {
self.functions.push(function);
self
}
#[must_use]
pub const fn with_retries(mut self, retries: usize) -> Self {
self.retries = Some(retries);
self
}
#[must_use]
pub const fn schema(&self) -> Option<&OutputSchema> {
self.schema.as_ref()
}
#[must_use]
pub fn validators(&self) -> &[Arc<dyn OutputValidator>] {
&self.validators
}
#[must_use]
pub fn functions(&self) -> &[DynOutputFunction] {
&self.functions
}
#[must_use]
pub const fn retries(&self) -> Option<usize> {
self.retries
}
#[must_use]
pub const fn mode(&self) -> Option<OutputMode> {
self.mode
}
#[must_use]
pub const fn text_output_allowed(&self) -> Option<bool> {
self.allow_text_output
}
#[must_use]
pub const fn image_output_allowed(&self) -> Option<bool> {
self.allow_image_output
}
pub(crate) fn into_parts(self) -> OutputPolicyParts {
(
self.schema,
self.validators,
self.functions,
self.retries,
self.mode,
self.allow_text_output,
self.allow_image_output,
)
}
}