mirror of
https://github.com/openai/codex.git
synced 2026-09-15 12:08:01 +00:00
deny unknown fields and add docs
This commit is contained in:
12
codex-rs/core/src/config/SCHEMA.md
Normal file
12
codex-rs/core/src/config/SCHEMA.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Config JSON Schema
|
||||
|
||||
We generate a JSON Schema for `~/.codex/config.toml` from the `ConfigToml` type
|
||||
and commit it at `docs/config.schema.json` for editor integration.
|
||||
|
||||
When you change any fields included in `ConfigToml` (or nested config types),
|
||||
regenerate the schema and update the fixture:
|
||||
|
||||
```
|
||||
just write-config-schema
|
||||
cargo test -p codex-core config_schema_matches_fixture
|
||||
```
|
||||
@@ -684,8 +684,13 @@ pub fn set_default_oss_provider(codex_home: &Path, provider: &str) -> std::io::R
|
||||
}
|
||||
|
||||
/// Base config deserialized from ~/.codex/config.toml.
|
||||
// The JSON Schema in `docs/config.schema.json` is generated from this struct.
|
||||
// If you add, remove, or rename fields, regenerate the schema via
|
||||
// `just write-config-schema` and update the fixture test.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct ConfigToml {
|
||||
pub test: Option<String>,
|
||||
/// Optional override of model selection.
|
||||
pub model: Option<String>,
|
||||
/// Review model override used by the `/review` feature.
|
||||
@@ -886,6 +891,7 @@ impl From<ConfigToml> for UserSavedConfig {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct ProjectConfig {
|
||||
pub trust_level: Option<TrustLevel>,
|
||||
}
|
||||
@@ -901,6 +907,7 @@ impl ProjectConfig {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct ToolsToml {
|
||||
#[serde(default, alias = "web_search_request")]
|
||||
pub web_search: Option<bool>,
|
||||
@@ -920,6 +927,7 @@ impl From<ToolsToml> for Tools {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct GhostSnapshotToml {
|
||||
/// Exclude untracked files larger than this many bytes from ghost snapshots.
|
||||
#[serde(alias = "ignore_untracked_files_over_bytes")]
|
||||
|
||||
@@ -12,6 +12,7 @@ use codex_protocol::openai_models::ReasoningEffort;
|
||||
/// Collection of common configuration options that a user can define as a unit
|
||||
/// in `config.toml`.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct ConfigProfile {
|
||||
pub model: Option<String>,
|
||||
/// The key in the `model_providers` map identifying the
|
||||
|
||||
@@ -48,7 +48,7 @@ pub(crate) fn features_schema(schema_gen: &mut SchemaGenerator) -> Schema {
|
||||
.properties
|
||||
.insert(feature.key.to_string(), schema_gen.subschema_for::<bool>());
|
||||
}
|
||||
validation.additional_properties = Some(Box::new(schema_gen.subschema_for::<bool>()));
|
||||
validation.additional_properties = Some(Box::new(Schema::Bool(false)));
|
||||
object.object = Some(Box::new(validation));
|
||||
|
||||
Schema::Object(object)
|
||||
@@ -84,6 +84,7 @@ fn mcp_server_schema(schema_gen: &mut SchemaGenerator) -> Schema {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
struct McpServerStdioSchema {
|
||||
command: String,
|
||||
#[serde(default)]
|
||||
@@ -109,6 +110,7 @@ struct McpServerStdioSchema {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
struct McpServerStreamableHttpSchema {
|
||||
url: String,
|
||||
#[serde(default)]
|
||||
@@ -145,9 +147,13 @@ mod tests {
|
||||
let fixture = std::fs::read_to_string(fixture_path).expect("read config schema fixture");
|
||||
let fixture_value: serde_json::Value =
|
||||
serde_json::from_str(&fixture).expect("parse config schema fixture");
|
||||
assert_eq!(fixture_value, schema_value);
|
||||
assert_eq!(
|
||||
fixture_value, schema_value,
|
||||
"Current schema for `config.toml` doesn't match the fixture. Run `just write-config-schema` to overwrite with your changes."
|
||||
);
|
||||
}
|
||||
|
||||
/// Overwrite the config schema fixture with the current schema.
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn write_config_schema_fixture() {
|
||||
|
||||
@@ -256,6 +256,7 @@ impl UriBasedFileOpener {
|
||||
|
||||
/// Settings that govern if and what will be written to `~/.codex/history.jsonl`.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct History {
|
||||
/// If true, history entries will not be written to disk.
|
||||
pub persistence: HistoryPersistence,
|
||||
@@ -279,6 +280,7 @@ pub enum HistoryPersistence {
|
||||
|
||||
/// Analytics settings loaded from config.toml. Fields are optional so we can apply defaults.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct AnalyticsConfigToml {
|
||||
/// When `false`, disables analytics across Codex product surfaces in this profile.
|
||||
pub enabled: Option<bool>,
|
||||
@@ -302,6 +304,7 @@ pub enum OtelHttpProtocol {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct OtelTlsConfig {
|
||||
pub ca_certificate: Option<AbsolutePathBuf>,
|
||||
@@ -311,6 +314,7 @@ pub struct OtelTlsConfig {
|
||||
|
||||
/// Which OTEL exporter to use.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum OtelExporterKind {
|
||||
None,
|
||||
@@ -334,6 +338,7 @@ pub enum OtelExporterKind {
|
||||
|
||||
/// OTEL settings loaded from config.toml. Fields are optional so we can apply defaults.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct OtelConfigToml {
|
||||
/// Log user prompt in traces
|
||||
pub log_user_prompt: Option<bool>,
|
||||
@@ -407,6 +412,7 @@ impl Default for ScrollInputMode {
|
||||
|
||||
/// Collection of settings that are specific to the TUI.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct Tui {
|
||||
/// Enable desktop notifications from the TUI when the terminal is unfocused.
|
||||
/// Defaults to `true`.
|
||||
@@ -546,6 +552,7 @@ const fn default_true() -> bool {
|
||||
/// (primarily the Codex IDE extension). NOTE: these are different from
|
||||
/// notifications - notices are warnings, NUX screens, acknowledgements, etc.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct Notice {
|
||||
/// Tracks whether the user has acknowledged the full access warning prompt.
|
||||
pub hide_full_access_warning: Option<bool>,
|
||||
@@ -569,6 +576,7 @@ impl Notice {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct SandboxWorkspaceWrite {
|
||||
#[serde(default)]
|
||||
pub writable_roots: Vec<AbsolutePathBuf>,
|
||||
@@ -609,6 +617,7 @@ pub enum ShellEnvironmentPolicyInherit {
|
||||
/// Policy for building the `env` when spawning a process via either the
|
||||
/// `shell` or `local_shell` tool.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct ShellEnvironmentPolicyToml {
|
||||
pub inherit: Option<ShellEnvironmentPolicyInherit>,
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ pub enum WireApi {
|
||||
|
||||
/// Serializable representation of a provider definition.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct ModelProviderInfo {
|
||||
/// Friendly display name.
|
||||
pub name: String,
|
||||
|
||||
@@ -118,9 +118,7 @@
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "boolean"
|
||||
}
|
||||
"additionalProperties": false
|
||||
},
|
||||
"file_opener": {
|
||||
"description": "Optional URI-based file opener. If set, citations to files in the model output will be hyperlinked using the specified URI scheme.",
|
||||
@@ -371,6 +369,7 @@
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
@@ -384,7 +383,8 @@
|
||||
"description": "When `false`, disables analytics across Codex product surfaces in this profile.",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"AskForApproval": {
|
||||
"description": "Determines the conditions under which the user is consulted to approve running the command proposed by Codex.",
|
||||
@@ -521,9 +521,7 @@
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "boolean"
|
||||
}
|
||||
"additionalProperties": false
|
||||
},
|
||||
"include_apply_patch_tool": {
|
||||
"type": "boolean"
|
||||
@@ -556,7 +554,8 @@
|
||||
"tools_web_search": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ForcedLoginMethod": {
|
||||
"type": "string",
|
||||
@@ -582,7 +581,8 @@
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"History": {
|
||||
"description": "Settings that govern if and what will be written to `~/.codex/history.jsonl`.",
|
||||
@@ -605,7 +605,8 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"HistoryPersistence": {
|
||||
"oneOf": [
|
||||
@@ -626,6 +627,7 @@
|
||||
]
|
||||
},
|
||||
"McpServerStdioSchema": {
|
||||
"description": "Schema-only representations of MCP server configs.\n\nKeep these in sync with the custom MCP config parsing in `crate::config::types::McpServerConfig`.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"command"
|
||||
@@ -693,7 +695,8 @@
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"McpServerStreamableHttpSchema": {
|
||||
"type": "object",
|
||||
@@ -756,7 +759,8 @@
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ModelProviderInfo": {
|
||||
"description": "Serializable representation of a provider definition.",
|
||||
@@ -838,7 +842,8 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Notice": {
|
||||
"description": "Settings for notices we display to users via the tui and app-server clients (primarily the Codex IDE extension). NOTE: these are different from notifications - notices are warnings, NUX screens, acknowledgements, etc.",
|
||||
@@ -872,7 +877,8 @@
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Notifications": {
|
||||
"anyOf": [
|
||||
@@ -941,7 +947,8 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"OtelExporterKind": {
|
||||
"description": "Which OTEL exporter to use.",
|
||||
@@ -987,7 +994,8 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@@ -1022,7 +1030,8 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@@ -1059,7 +1068,8 @@
|
||||
"client-private-key": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ProjectConfig": {
|
||||
"type": "object",
|
||||
@@ -1067,7 +1077,8 @@
|
||||
"trust_level": {
|
||||
"$ref": "#/definitions/TrustLevel"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ReasoningEffort": {
|
||||
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
||||
@@ -1131,7 +1142,8 @@
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ScrollInputMode": {
|
||||
"description": "How TUI2 should interpret mouse scroll events.\n\nTerminals generally encode both mouse wheels and trackpads as the same \"scroll up/down\" mouse button events, without a magnitude. This setting controls whether Codex uses a heuristic to infer wheel vs trackpad per stream, or forces a specific behavior.",
|
||||
@@ -1217,7 +1229,8 @@
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ToolsToml": {
|
||||
"type": "object",
|
||||
@@ -1231,7 +1244,8 @@
|
||||
"default": null,
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"TrustLevel": {
|
||||
"description": "Represents the trust level for a project directory. This determines the approval policy and sandbox mode applied.",
|
||||
@@ -1320,7 +1334,8 @@
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"UriBasedFileOpener": {
|
||||
"oneOf": [
|
||||
|
||||
4
justfile
4
justfile
@@ -56,3 +56,7 @@ build-for-release:
|
||||
# Run the MCP server
|
||||
mcp-server-run *args:
|
||||
cargo run -p codex-mcp-server -- "$@"
|
||||
|
||||
# Regenerate the json schema for config.toml from the current config types.
|
||||
write-config-schema:
|
||||
cargo test -p codex-core write_config_schema_fixture -- --ignored
|
||||
|
||||
Reference in New Issue
Block a user