objectiveai_sdk/cli/command/response_schema.rs
1//! [`ResponseSchema`] — newtype wrapper around [`schemars::Schema`]
2//! that delegates its `JsonSchema` impl to [`serde_json::Value`].
3//!
4//! Every cli `*-schema` leaf subcommand emits a JSON Schema document
5//! as its response. The wire shape is opaque JSON — any valid schema
6//! is acceptable. Typing the response as `schemars::Schema` directly
7//! makes that wire shape strongly typed, but `schemars::Schema`'s own
8//! JsonSchema impl emits `{"type": ["object", "boolean"]}` (because
9//! the JSON Schema spec says a (sub)schema can be either an object or
10//! a bare boolean). That type array trips the
11//! `no_type_arrays_outside_properties` builder property test.
12//!
13//! The orphan rule prevents us from `impl JsonSchema for schemars::Schema`
14//! directly. This wrapper provides the same in-process typing
15//! (a `schemars::Schema` inside) while overriding the JsonSchema impl
16//! to behave exactly like `serde_json::Value` (no constraints, no
17//! type array). Serialization is transparent — the wire shape is
18//! identical to `schemars::Schema`'s.
19
20use objectiveai_sdk_macros::schema_override;
21
22#[schema_override(Ref)]
23#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
24#[serde(transparent)]
25pub struct ResponseSchema(pub schemars::Schema);
26
27impl schemars::JsonSchema for ResponseSchema {
28 fn schema_name() -> std::borrow::Cow<'static, str> {
29 <serde_json::Value as schemars::JsonSchema>::schema_name()
30 }
31
32 fn json_schema(
33 generator: &mut schemars::SchemaGenerator,
34 ) -> schemars::Schema {
35 <serde_json::Value as schemars::JsonSchema>::json_schema(generator)
36 }
37
38 fn inline_schema() -> bool {
39 // ALWAYS inline. Bare `serde_json::Value` fields embed an
40 // inline `{}` (unconstrained) schema, and this wrapper must
41 // behave identically. Without this, schemars treats
42 // `ResponseSchema` as a referenceable named type and every
43 // `*-schema` response becomes a `$ref: "AnyValue"`, forcing
44 // `Value` itself to exist as a registered standalone title.
45 true
46 }
47}