1use std::{fmt, fs, path::Path};
2
3use schemars::schema_for;
4
5use crate::*;
6
7#[derive(Debug)]
8pub enum BindingExportError {
9 Arguments(String),
10 Io(std::io::Error),
11 Json(serde_json::Error),
12}
13
14impl fmt::Display for BindingExportError {
15 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
16 match self {
17 Self::Arguments(error) => {
18 write!(formatter, "invalid binding generator arguments: {error}")
19 }
20 Self::Io(error) => write!(formatter, "binding output failed: {error}"),
21 Self::Json(error) => write!(formatter, "schema encoding failed: {error}"),
22 }
23 }
24}
25
26impl std::error::Error for BindingExportError {}
27
28impl From<std::io::Error> for BindingExportError {
29 fn from(value: std::io::Error) -> Self {
30 Self::Io(value)
31 }
32}
33impl From<serde_json::Error> for BindingExportError {
34 fn from(value: serde_json::Error) -> Self {
35 Self::Json(value)
36 }
37}
38macro_rules! protocol_roots {
39 ($macro:ident) => {
40 $macro!(
41 ClientHello,
42 ServerHello,
43 Request,
44 Response,
45 Notification,
46 ExtensionInitializeParams,
47 ExtensionInitializeResult,
48 ExtensionProducerRegisterParams,
49 ExtensionProducerRegisterResult,
50 ExtensionProducerSendParams,
51 ExtensionProducerSendResult,
52 ExtensionProducerUnregisterParams,
53 ExtensionProducerUnregisterResult,
54 ExtensionProducerDiscardParams,
55 ExtensionProducerDiscardResult,
56 ExtensionRecoveryStartParams,
57 ExtensionRecoveryCompleteParams,
58 ExtensionRecoveryCompleteResult,
59 ExtensionPingParams,
60 ExtensionPingResult,
61 ExtensionShutdownParams,
62 ExtensionToolCallParams,
63 ExtensionToolCallResult,
64 ExtensionEventParams,
65 ExtensionBusEventParams,
66 ExtensionEmitParams,
67 ExtensionEmitResultParams,
68 ExtensionToolBeforeCallParams,
69 ExtensionToolBeforeCallResult,
70 ExtensionToolAfterResultParams,
71 ExtensionToolAfterResultResult,
72 ExtensionAgentBeforeStartParams,
73 ExtensionAgentBeforeStartResult,
74 ExtensionSessionBeforeCompactParams,
75 ExtensionSessionBeforeCompactResult,
76 ExtensionUserBeforeInputParams,
77 ExtensionUserBeforeInputResult,
78 ExtensionModelBeforeRequestParams,
79 ExtensionModelBeforeRequestResult,
80 ExtensionProviderBeforeHeadersParams,
81 ExtensionProviderBeforeHeadersResult,
82 ExtensionProviderBeforeRequestParams,
83 ExtensionProviderBeforeRequestResult,
84 ExtensionProviderAfterResponseParams,
85 ExtensionProviderAfterResponseResult,
86 ExtensionMessageEndParams,
87 ExtensionMessageEndResult,
88 ExtensionModelBeforeSelectParams,
89 ExtensionAllowBlockResult,
90 ExtensionSessionBeforeForkParams,
91 ExtensionSessionBeforeRevertParams,
92 ExtensionSessionBeforeRevertResult,
93 SessionMeta,
94 StoredEvent,
95 EventPayload,
96 EventSubscriptionMessage,
97 OutputDelta,
98 OutputGap,
99 OutputSnapshotEnvelope,
100 SessionCreateParams,
101 SessionCreateResult,
102 SessionListParams,
103 SessionListResult,
104 SessionGetParams,
105 SessionGetResult,
106 SessionGoalGetParams,
107 SessionGoalGetResult,
108 SessionGoalSetParams,
109 SessionGoalSetResult,
110 SessionGoalLifecycleParams,
111 SessionGoalLifecycleResult,
112 SessionProducersParams,
113 SessionProducersResult,
114 GoalGetParams,
115 GoalGetResult,
116 GoalUpdateParams,
117 GoalUpdateResult,
118 SessionUsageParams,
119 SessionUsageResult,
120 SessionTreeUsageResult,
121 AgentUsageParams,
122 AgentUsageResult,
123 GlobalUsageParams,
124 GlobalUsageResult,
125 ModelUsageRollup,
126 SessionChildrenParams,
127 SessionChildrenResult,
128 SessionTreeParams,
129 SessionTreeResult,
130 SessionResumeParams,
131 SessionResumeResult,
132 SessionSetPermissionModeParams,
133 SessionSetPermissionModeResult,
134 SessionPermissionGetParams,
135 SessionPermissionGetResult,
136 SessionPermissionSetParams,
137 SessionPermissionClearParams,
138 SessionPermissionMutationResult,
139 SkillsListParams,
140 SkillsListResult,
141 SkillsGetParams,
142 SkillsGetResult,
143 SessionCompactParams,
144 SessionCompactResult,
145 SessionRevertParams,
146 SessionRevertResult,
147 SessionForkParams,
148 SessionForkResult,
149 RunStartParams,
150 RunStartResult,
151 RunStartConflict,
152 RunSteerParams,
153 RunSteerResult,
154 RunRecallSteerParams,
155 RunRecallSteerResult,
156 RunCancelParams,
157 RunCancelResult,
158 RunToolStdinParams,
159 RunToolStdinResult,
160 SessionRenameParams,
161 SessionRenameResult,
162 SessionRenameError,
163 EventsSubscribeParams,
164 EventsSubscribeResult,
165 ApprovalRespondParams,
166 ApprovalRespondResult,
167 ApprovalRespondError,
168 ApprovalListParams,
169 ApprovalListResult,
170 McpAuthBeginParams,
171 McpAuthBeginResult,
172 McpAuthCancelParams,
173 McpAuthCancelResult,
174 McpServerListParams,
175 McpServerListResult,
176 McpServerAddParams,
177 McpServerEditParams,
178 McpServerNameParams,
179 McpServerSetEnabledParams,
180 McpServerPersistParams,
181 McpServerMutationResult,
182 RuntimeSnapshotGetParams,
183 RuntimeSnapshotResult,
184 RuntimeChangedNotification,
185 ProviderConnectResult,
186 ProviderConnectError,
187 ProviderDisconnectParams,
188 ProviderDisconnectResult,
189 ProviderDisconnectError,
190 ModelSnapshotManifestV1
191 )
192 };
193}
194
195#[must_use]
196pub fn json_schema_documents() -> Vec<(&'static str, schemars::Schema)> {
197 macro_rules! collect {
198 ($($type:ty),+ $(,)?) => {{
199 vec![$((concat!(stringify!($type), ".schema.json"), schema_for!($type))),+]
200 }};
201 }
202 protocol_roots!(collect)
203}
204
205pub fn export_json_schema_set(output: &Path) -> Result<(), BindingExportError> {
206 if output.exists() {
207 fs::remove_dir_all(output)?;
208 }
209 fs::create_dir_all(output)?;
210 let documents = json_schema_documents();
211 let filenames = documents
212 .iter()
213 .map(|(filename, _)| *filename)
214 .collect::<Vec<_>>();
215 for (filename, schema) in documents {
216 let bytes = serde_json::to_vec_pretty(&schema)?;
217 fs::write(output.join(filename), bytes)?;
218 }
219 fs::write(
220 output.join("manifest.json"),
221 serde_json::to_vec_pretty(&serde_json::json!({
222 "protocol_version": PROTOCOL_VERSION,
223 "schemas": filenames,
224 }))?,
225 )?;
226 Ok(())
227}