Commit Graph

6 Commits

  • feat: change ConfigLayerName into a disjoint union rather than a simple enum (#8095)
    This attempts to tighten up the types related to "config layers."
    Currently, `ConfigLayerEntry` is defined as follows:
    
    
    https://github.com/openai/codex/blob/bef36f4ae765f471d7cd69372fcf1b92c8f0367a/codex-rs/core/src/config_loader/state.rs#L19-L25
    
    but the `source` field is a bit of a lie, as:
    
    - for `ConfigLayerName::Mdm`, it is
    `"com.openai.codex/config_toml_base64"`
    - for `ConfigLayerName::SessionFlags`, it is `"--config"`
    - for `ConfigLayerName::User`, it is `"config.toml"` (just the file
    name, not the path to the `config.toml` on disk that was read)
    - for `ConfigLayerName::System`, it seems like it is usually
    `/etc/codex/managed_config.toml` in practice, though on Windows, it is
    `%CODEX_HOME%/managed_config.toml`:
    
    
    https://github.com/openai/codex/blob/bef36f4ae765f471d7cd69372fcf1b92c8f0367a/codex-rs/core/src/config_loader/layer_io.rs#L84-L101
    
    All that is to say, in three out of the four `ConfigLayerName`, `source`
    is a `PathBuf` that is not an absolute path (or even a true path).
    
    This PR tries to uplevel things by eliminating `source` from
    `ConfigLayerEntry` and turning `ConfigLayerName` into a disjoint union
    named `ConfigLayerSource` that has the appropriate metadata for each
    variant, favoring the use of `AbsolutePathBuf` where appropriate:
    
    ```rust
    pub enum ConfigLayerSource {
        /// Managed preferences layer delivered by MDM (macOS only).
        #[serde(rename_all = "camelCase")]
        #[ts(rename_all = "camelCase")]
        Mdm { domain: String, key: String },
        /// Managed config layer from a file (usually `managed_config.toml`).
        #[serde(rename_all = "camelCase")]
        #[ts(rename_all = "camelCase")]
        System { file: AbsolutePathBuf },
        /// Session-layer overrides supplied via `-c`/`--config`.
        SessionFlags,
        /// User config layer from a file (usually `config.toml`).
        #[serde(rename_all = "camelCase")]
        #[ts(rename_all = "camelCase")]
        User { file: AbsolutePathBuf },
    }
    ```
  • fix: introduce AbsolutePathBuf as part of sandbox config (#7856)
    Changes the `writable_roots` field of the `WorkspaceWrite` variant of
    the `SandboxPolicy` enum from `Vec<PathBuf>` to `Vec<AbsolutePathBuf>`.
    This is helpful because now callers can be sure the value is an absolute
    path rather than a relative one. (Though when using an absolute path in
    a Seatbelt config policy, we still have to _canonicalize_ it first.)
    
    Because `writable_roots` can be read from a config file, it is important
    that we are able to resolve relative paths properly using the parent
    folder of the config file as the base path.
  • [app-server-protocol] Add types for config (#7658)
    Currently the config returned by `config/read` in untyped. Add types so
    it's easier for client to parse the config. Since currently configs are
    all defined in snake case we'll keep that instead of using camel case
    like the rest of V2.
    
    Sample output by testing using the app server test client:
    ```
    {
    <   "id": "f28449f4-b015-459b-b07b-eef06980165d",
    <   "result": {
    <     "config": {
    <       "approvalPolicy": null,
    <       "compactPrompt": null,
    <       "developerInstructions": null,
    <       "features": {
    <         "experimental_use_rmcp_client": true
    <       },
    <       "forcedChatgptWorkspaceId": null,
    <       "forcedLoginMethod": null,
    <       "instructions": null,
    <       "model": "gpt-5.1-codex-max",
    <       "modelAutoCompactTokenLimit": null,
    <       "modelContextWindow": null,
    <       "modelProvider": null,
    <       "modelReasoningEffort": null,
    <       "modelReasoningSummary": null,
    <       "modelVerbosity": null,
    <       "model_providers": {
    <         "local": {
    <           "base_url": "http://localhost:8061/api/codex",
    <           "env_http_headers": {
    <             "ChatGPT-Account-ID": "OPENAI_ACCOUNT_ID"
    <           },
    <           "env_key": "CHATGPT_TOKEN_STAGING",
    <           "name": "local",
    <           "wire_api": "responses"
    <         }
    <       },
    <       "model_reasoning_effort": "medium",
    <       "notice": {
    <         "hide_gpt-5.1-codex-max_migration_prompt": true,
    <         "hide_gpt5_1_migration_prompt": true
    <       },
    <       "profile": null,
    <       "profiles": {},
    <       "projects": {
    <         "/Users/celia/code": {
    <           "trust_level": "trusted"
    <         },
    <         "/Users/celia/code/codex": {
    <           "trust_level": "trusted"
    <         },
    <         "/Users/celia/code/openai": {
    <           "trust_level": "trusted"
    <         }
    <       },
    <       "reviewModel": null,
    <       "sandboxMode": null,
    <       "sandboxWorkspaceWrite": null,
    <       "tools": {
    <         "viewImage": null,
    <         "webSearch": null
    <       }
    <     },
    <     "origins": {
    <       "features.experimental_use_rmcp_client": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model_providers.local.base_url": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model_providers.local.env_http_headers.ChatGPT-Account-ID": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model_providers.local.env_key": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model_providers.local.name": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model_providers.local.wire_api": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model_reasoning_effort": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "notice.hide_gpt-5.1-codex-max_migration_prompt": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "notice.hide_gpt5_1_migration_prompt": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "projects./Users/celia/code.trust_level": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "projects./Users/celia/code/codex.trust_level": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "projects./Users/celia/code/openai.trust_level": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "tools.web_search": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       }
    <     }
    <   }
    < }
    ```
  • [app-server] make file_path for config optional (#7560)
    When we are writing to config using `config/value/write` or
    `config/batchWrite`, it always require a `config/read` before it right
    now in order to get the correct file path to write to. make this
    optional so we read from the default user config file if this is not
    passed in.