Skip to main content

cookie_agent_protocol/
lib.rs

1//! Exact cookie-agent protocol 20 with versionless session events.
2//!
3//! This crate intentionally contains no compatibility aliases or decoders.
4
5use std::borrow::Cow;
6
7use schemars::{JsonSchema, Schema, SchemaGenerator, json_schema};
8use serde::{Deserialize, Serialize};
9
10mod tool_output;
11pub use tool_output::*;
12
13pub(crate) struct NullableSchema<T>(std::marker::PhantomData<T>);
14
15impl<T: JsonSchema> JsonSchema for NullableSchema<T> {
16    fn inline_schema() -> bool {
17        true
18    }
19    fn schema_name() -> Cow<'static, str> {
20        Cow::Owned(format!("Nullable{}", T::schema_name()))
21    }
22    fn json_schema(generator: &mut SchemaGenerator) -> Schema {
23        generator.subschema_for::<Option<T>>()
24    }
25}
26
27pub(crate) fn deserialize_required_option<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
28where
29    D: serde::Deserializer<'de>,
30    T: Deserialize<'de>,
31{
32    Option::<T>::deserialize(deserializer)
33}
34
35#[derive(Deserialize)]
36#[serde(deny_unknown_fields)]
37struct RequiredModelSelectionWire {
38    model: ModelKey,
39    #[serde(deserialize_with = "deserialize_required_option")]
40    variant: Option<VariantId>,
41}
42
43pub(crate) fn deserialize_required_model_selection<'de, D>(
44    deserializer: D,
45) -> Result<ModelSelection, D::Error>
46where
47    D: serde::Deserializer<'de>,
48{
49    let wire = RequiredModelSelectionWire::deserialize(deserializer)?;
50    Ok(ModelSelection {
51        model: wire.model,
52        variant: wire.variant,
53    })
54}
55
56pub(crate) fn deserialize_required_model_selections<'de, D>(
57    deserializer: D,
58) -> Result<Vec<ModelSelection>, D::Error>
59where
60    D: serde::Deserializer<'de>,
61{
62    Vec::<RequiredModelSelectionWire>::deserialize(deserializer).map(|values| {
63        values
64            .into_iter()
65            .map(|wire| ModelSelection {
66                model: wire.model,
67                variant: wire.variant,
68            })
69            .collect()
70    })
71}
72
73pub(crate) struct RequiredModelSelectionSchema;
74
75impl JsonSchema for RequiredModelSelectionSchema {
76    fn inline_schema() -> bool {
77        true
78    }
79
80    fn schema_name() -> Cow<'static, str> {
81        ModelSelection::schema_name()
82    }
83
84    fn json_schema(generator: &mut SchemaGenerator) -> Schema {
85        let mut schema = ModelSelection::json_schema(generator);
86        schema
87            .ensure_object()
88            .insert("required".into(), serde_json::json!(["model", "variant"]));
89        schema
90    }
91}
92
93mod agent;
94mod approval;
95mod bindings;
96pub mod diagnostics;
97mod event;
98mod extension;
99mod goal;
100mod identity;
101mod manifest;
102mod model;
103pub mod paths;
104mod producer;
105mod provider;
106mod rpc;
107mod runtime;
108mod session;
109mod session_model;
110mod setup_value;
111
112pub use agent::*;
113pub use approval::*;
114pub use bindings::*;
115pub use cookie_agent_identity::{
116    AdapterId, AgentId, AgentRevision, AuthFieldName, AuthMethodId, AuthParameterId, AuthRecipeId,
117    CacheEntryId, CacheRevision, CanonicalModelId, CatalogRevision, IdentityError, ManifestEntryId,
118    ManifestRevision, ModelKey, ModelRevision, ModelSelection, ModelSnapshotRevision,
119    ProtocolRecipeId, ProviderId, ProviderModelId, ProviderRecipeId, ProviderSetupRecipeId,
120    ProviderStateRevision, ProviderStoreRevision, RecipeCompilerVersion, RecipeRegistryRevision,
121    RuntimeRevision, SafeCode, SetupFieldId, StoreEntryId, VariantId, WildcardPattern,
122};
123pub use event::*;
124pub use extension::*;
125pub use goal::*;
126pub use identity::*;
127pub use manifest::*;
128pub use model::*;
129pub use producer::*;
130pub use provider::*;
131pub use rpc::*;
132pub use runtime::*;
133pub use session::*;
134pub use session_model::*;
135pub use setup_value::*;
136
137/// The only protocol version supported by this build.
138pub const PROTOCOL_VERSION: u32 = 20;
139/// The only coherent runtime snapshot schema supported by this build.
140pub const RUNTIME_SNAPSHOT_SCHEMA_VERSION: u32 = 5;
141
142macro_rules! exact_numeric_wire_type {
143    ($name:ident, $value:expr, $description:literal) => {
144        #[doc = $description]
145        #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
146        pub struct $name(());
147
148        impl $name {
149            #[must_use]
150            pub const fn current() -> Self {
151                Self(())
152            }
153
154            #[must_use]
155            pub const fn value(self) -> u32 {
156                $value
157            }
158        }
159
160        impl Serialize for $name {
161            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
162            where
163                S: serde::Serializer,
164            {
165                serializer.serialize_u32($value)
166            }
167        }
168
169        impl<'de> Deserialize<'de> for $name {
170            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
171            where
172                D: serde::Deserializer<'de>,
173            {
174                let value = u32::deserialize(deserializer)?;
175                if value == $value {
176                    Ok(Self::current())
177                } else {
178                    Err(serde::de::Error::custom(format!(
179                        "unsupported exact wire version {value}; expected {}",
180                        $value
181                    )))
182                }
183            }
184        }
185
186        impl JsonSchema for $name {
187            fn inline_schema() -> bool {
188                true
189            }
190
191            fn schema_name() -> Cow<'static, str> {
192                Cow::Borrowed(stringify!($name))
193            }
194
195            fn json_schema(_generator: &mut SchemaGenerator) -> Schema {
196                json_schema!({"type": "integer", "const": $value})
197            }
198        }
199    };
200}
201
202exact_numeric_wire_type!(ProtocolVersion, 20, "The exact protocol wire version.");
203exact_numeric_wire_type!(
204    RuntimeSnapshotSchemaVersion,
205    5,
206    "The exact coherent runtime snapshot schema version."
207);
208
209#[cfg(test)]
210mod goal_producer_tests;
211#[cfg(test)]
212mod tests;