Skip to main content

codex/cli/
app_server.rs

1use crate::{CliOverridesPatch, ConfigOverride, FlagState};
2use std::{path::PathBuf, process::ExitStatus};
3
4/// Target for app-server code generation.
5#[derive(Clone, Debug, Eq, PartialEq)]
6pub enum AppServerCodegenTarget {
7    /// Emits TypeScript bindings for the app-server protocol. Optionally formats the output with Prettier.
8    TypeScript { prettier: Option<PathBuf> },
9    /// Emits a JSON schema bundle for the app-server protocol.
10    JsonSchema,
11}
12
13impl AppServerCodegenTarget {
14    pub(crate) fn subcommand(&self) -> &'static str {
15        match self {
16            AppServerCodegenTarget::TypeScript { .. } => "generate-ts",
17            AppServerCodegenTarget::JsonSchema => "generate-json-schema",
18        }
19    }
20
21    pub(crate) fn prettier(&self) -> Option<&PathBuf> {
22        match self {
23            AppServerCodegenTarget::TypeScript { prettier } => prettier.as_ref(),
24            AppServerCodegenTarget::JsonSchema => None,
25        }
26    }
27}
28
29/// Request for `codex app-server generate-ts` or `generate-json-schema`.
30#[derive(Clone, Debug, Eq, PartialEq)]
31pub struct AppServerCodegenRequest {
32    /// Codegen target and optional Prettier path (TypeScript only).
33    pub target: AppServerCodegenTarget,
34    /// Output directory passed to `--out`; created if missing.
35    pub out_dir: PathBuf,
36    /// Passes `--experimental` to the app-server codegen subcommand when enabled.
37    pub experimental: bool,
38    /// Per-call CLI overrides layered on top of the builder.
39    pub overrides: CliOverridesPatch,
40}
41
42impl AppServerCodegenRequest {
43    /// Generates TypeScript bindings into `out_dir`.
44    pub fn typescript(out_dir: impl Into<PathBuf>) -> Self {
45        Self {
46            target: AppServerCodegenTarget::TypeScript { prettier: None },
47            out_dir: out_dir.into(),
48            experimental: false,
49            overrides: CliOverridesPatch::default(),
50        }
51    }
52
53    /// Generates a JSON schema bundle into `out_dir`.
54    pub fn json_schema(out_dir: impl Into<PathBuf>) -> Self {
55        Self {
56            target: AppServerCodegenTarget::JsonSchema,
57            out_dir: out_dir.into(),
58            experimental: false,
59            overrides: CliOverridesPatch::default(),
60        }
61    }
62
63    /// Controls whether `--experimental` is passed to the codegen subcommand.
64    pub fn experimental(mut self, enable: bool) -> Self {
65        self.experimental = enable;
66        self
67    }
68
69    /// Formats TypeScript output with the provided Prettier executable (no-op for JSON schema).
70    pub fn prettier(mut self, prettier: impl Into<PathBuf>) -> Self {
71        if let AppServerCodegenTarget::TypeScript { prettier: slot } = &mut self.target {
72            *slot = Some(prettier.into());
73        }
74        self
75    }
76
77    /// Replaces the default CLI overrides for this request.
78    pub fn with_overrides(mut self, overrides: CliOverridesPatch) -> Self {
79        self.overrides = overrides;
80        self
81    }
82
83    /// Adds a `--config key=value` override for this request.
84    pub fn config_override(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
85        self.overrides
86            .config_overrides
87            .push(ConfigOverride::new(key, value));
88        self
89    }
90
91    /// Adds a raw `--config key=value` override without validation.
92    pub fn config_override_raw(mut self, raw: impl Into<String>) -> Self {
93        self.overrides
94            .config_overrides
95            .push(ConfigOverride::from_raw(raw));
96        self
97    }
98
99    /// Sets the config profile (`--profile`) for this request.
100    pub fn profile(mut self, profile: impl Into<String>) -> Self {
101        let profile = profile.into();
102        self.overrides.profile = (!profile.trim().is_empty()).then_some(profile);
103        self
104    }
105
106    /// Requests the CLI `--oss` flag for this codegen call.
107    pub fn oss(mut self, enable: bool) -> Self {
108        self.overrides.oss = if enable {
109            FlagState::Enable
110        } else {
111            FlagState::Disable
112        };
113        self
114    }
115
116    /// Adds a `--enable <feature>` toggle for this codegen call.
117    pub fn enable_feature(mut self, name: impl Into<String>) -> Self {
118        self.overrides.feature_toggles.enable.push(name.into());
119        self
120    }
121
122    /// Adds a `--disable <feature>` toggle for this codegen call.
123    pub fn disable_feature(mut self, name: impl Into<String>) -> Self {
124        self.overrides.feature_toggles.disable.push(name.into());
125        self
126    }
127
128    /// Controls whether `--search` is passed through to Codex.
129    pub fn search(mut self, enable: bool) -> Self {
130        self.overrides.search = if enable {
131            FlagState::Enable
132        } else {
133            FlagState::Disable
134        };
135        self
136    }
137}
138
139/// Captured output from app-server codegen commands.
140#[derive(Clone, Debug)]
141pub struct AppServerCodegenOutput {
142    /// Exit status returned by the subcommand.
143    pub status: ExitStatus,
144    /// Captured stdout (mirrored to the console when `mirror_stdout` is true).
145    pub stdout: String,
146    /// Captured stderr (mirrored unless `quiet` is set).
147    pub stderr: String,
148    /// Output directory passed to `--out`.
149    pub out_dir: PathBuf,
150}