systemprompt_models/schema/
capabilities.rs1use serde_json::Value;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub struct SchemaComposition {
18 pub allof: bool,
19 pub anyof: bool,
20 pub oneof: bool,
21 pub if_then_else: bool,
22 pub not: bool,
23}
24
25#[expect(
26 clippy::struct_excessive_bools,
27 reason = "schema feature matrix: each bool is an independent JSON-Schema construct the \
28 provider does or does not accept, not state"
29)]
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub struct SchemaFeatures {
32 pub references: bool,
33 pub definitions: bool,
34 pub additional_properties: bool,
35 pub const_values: bool,
36 pub exclusive_bounds: bool,
37 pub property_names: bool,
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41pub struct ProviderCapabilities {
42 pub composition: SchemaComposition,
43 pub features: SchemaFeatures,
44}
45
46impl ProviderCapabilities {
47 pub const fn anthropic() -> Self {
48 Self {
49 composition: SchemaComposition {
50 allof: true,
51 anyof: true,
52 oneof: true,
53 if_then_else: true,
54 not: true,
55 },
56 features: SchemaFeatures {
57 references: true,
58 definitions: true,
59 additional_properties: true,
60 const_values: true,
61 exclusive_bounds: true,
62 property_names: true,
63 },
64 }
65 }
66
67 pub const fn openai() -> Self {
68 Self {
69 composition: SchemaComposition {
70 allof: true,
71 anyof: true,
72 oneof: true,
73 if_then_else: false,
74 not: false,
75 },
76 features: SchemaFeatures {
77 references: true,
78 definitions: true,
79 additional_properties: true,
80 const_values: true,
81 exclusive_bounds: true,
82 property_names: true,
83 },
84 }
85 }
86
87 pub const fn gemini() -> Self {
88 Self {
89 composition: SchemaComposition {
90 allof: false,
91 anyof: true,
92 oneof: false,
93 if_then_else: false,
94 not: false,
95 },
96 features: SchemaFeatures {
97 references: false,
98 definitions: false,
99 additional_properties: false,
100 const_values: false,
101 exclusive_bounds: false,
102 property_names: false,
103 },
104 }
105 }
106
107 pub fn requires_transformation(&self, schema: &Value) -> bool {
108 if let Some(obj) = schema.as_object() {
109 if obj.contains_key("allOf") && !self.composition.allof {
110 return true;
111 }
112 if obj.contains_key("anyOf") && !self.composition.anyof {
113 return true;
114 }
115 if obj.contains_key("oneOf") && !self.composition.oneof {
116 return true;
117 }
118 if obj.contains_key("if") && !self.composition.if_then_else {
119 return true;
120 }
121 if obj.contains_key("$ref") && !self.features.references {
122 return true;
123 }
124 if (obj.contains_key("definitions") || obj.contains_key("$defs"))
125 && !self.features.definitions
126 {
127 return true;
128 }
129 if obj.contains_key("not") && !self.composition.not {
130 return true;
131 }
132 }
133 false
134 }
135}