Skip to main content

codex_app_server_client/
compat.rs

1use std::process::Command;
2
3use serde::{Deserialize, Serialize};
4
5include!(concat!(env!("OUT_DIR"), "/compat_generated.rs"));
6
7#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
8pub struct SurfaceSummary {
9    pub client_requests: usize,
10    pub server_requests: usize,
11    pub server_notifications: usize,
12    pub client_notifications: usize,
13}
14
15impl SurfaceSummary {
16    pub const fn current() -> Self {
17        Self {
18            client_requests: CLIENT_REQUEST_METHOD_COUNT,
19            server_requests: SERVER_REQUEST_METHOD_COUNT,
20            server_notifications: SERVER_NOTIFICATION_METHOD_COUNT,
21            client_notifications: CLIENT_NOTIFICATION_METHOD_COUNT,
22        }
23    }
24}
25
26#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
27pub struct CompatibilityReport {
28    pub schema_codex_version: String,
29    pub installed_codex_version: Option<String>,
30    pub surface: SurfaceSummary,
31}
32
33impl CompatibilityReport {
34    pub fn current() -> Self {
35        Self::from_installed_version(installed_codex_version())
36    }
37
38    pub fn from_installed_version(installed_codex_version: Option<String>) -> Self {
39        Self {
40            schema_codex_version: CODEX_SCHEMA_VERSION.trim().to_owned(),
41            installed_codex_version,
42            surface: SurfaceSummary::current(),
43        }
44    }
45
46    pub fn schema_matches_installed(&self) -> bool {
47        self.installed_codex_version
48            .as_deref()
49            .map(str::trim)
50            .is_some_and(|installed| installed == self.schema_codex_version)
51    }
52}
53
54fn installed_codex_version() -> Option<String> {
55    let output = Command::new("codex").arg("--version").output().ok()?;
56    if !output.status.success() {
57        return None;
58    }
59    let version = String::from_utf8(output.stdout).ok()?;
60    let version = version.trim();
61    (!version.is_empty()).then(|| version.to_owned())
62}