@smbcloud / cli / commits / 4d1cf59

fix: bound ControlKit diagnostics and strengthen schema coverage

Seto Elkahfi committed Aug 25, 2026 at 14:03 UTC 4d1cf592e9dc023aeeb2a8823aa814a0a36878fb
2 files changed +32 -5
crates/xcrs/src/mcp.rs
+16 -2
@@ -2218,8 +2218,22 @@ mod tests {
2218 .iter()
2219 .find(|tool| tool.name.as_ref() == "orientation_get")
2220 .expect("orientation_get should be registered");
2221 -
2222 - assert!(tool.input_schema["properties"].get("bundle_id").is_none());
2221 + let properties = tool.input_schema["properties"]
2222 + .as_object()
2223 + .expect("orientation_get properties should be an object");
2224 +
2225 + for property in [
2226 + "simulator_name",
2227 + "simulator_udid",
2228 + "host",
2229 + "controlkit_port",
2230 + ] {
2231 + assert!(
2232 + properties.contains_key(property),
2233 + "orientation_get should advertise {property}"
2234 + );
2235 + }
2236 + assert!(!properties.contains_key("bundle_id"));
2237 }
2238
2239 #[test]
crates/xcrs/src/xcrs.rs
+16 -3
@@ -11,6 +11,7 @@ pub mod mcp;
11
12 const IOS_SIMULATOR_DESTINATION_PREFIX: &str = "platform=iOS Simulator,id=";
13 const CONTROLKIT_METHOD_NOT_FOUND: i64 = -32601;
14 +const CONTROLKIT_RUNNER_INFO_TIMEOUT: Duration = Duration::from_secs(2);
15
16 pub fn encode_base64(data: impl AsRef<[u8]>) -> String {
17 use base64::{engine::general_purpose::STANDARD, Engine};
@@ -139,8 +140,13 @@ impl ControlKit {
140 == Some(CONTROLKIT_METHOD_NOT_FOUND)
141 && method != "device.info"
142 {
142 - match self.send("device.info", serde_json::json!({})).await {
143 - Ok(body) => match body.get("result") {
143 + match tokio::time::timeout(
144 + CONTROLKIT_RUNNER_INFO_TIMEOUT,
145 + self.send("device.info", serde_json::json!({})),
146 + )
147 + .await
148 + {
149 + Ok(Ok(body)) => match body.get("result") {
150 Some(result) => (Some(result.clone()), None),
151 None => {
152 let reason = body
@@ -152,7 +158,14 @@ impl ControlKit {
158 (None, Some(reason))
159 }
160 },
155 - Err(error) => (None, Some(error.to_string())),
161 + Ok(Err(error)) => (None, Some(error.to_string())),
162 + Err(_) => (
163 + None,
164 + Some(format!(
165 + "device.info timed out after {} seconds",
166 + CONTROLKIT_RUNNER_INFO_TIMEOUT.as_secs()
167 + )),
168 + ),
169 }
170 } else {
171 (None, None)