Commit Graph

14 Commits

  • Fix: Skip Option<()> schema generation to avoid invalid Windows filenames (#7479) (#7969)
    ## Problem
    
    When generating JSON schemas on Windows, the `codex app-server
    generate-json-schema` command fails with a filename error:
    ```text
    Error: Failed to write JSON schema for Option<()>
    Caused by:
        0: Failed to write .\Option<()>.json
        1: The filename, directory name, or volume label syntax is incorrect. (os error 123)
    ```
    This occurs because Windows doesn't allow certain characters in
    filenames, specifically the angle brackets **<>** used in the
    **Option<()>** type name.
    
    ## Root Cause
    
    The schema generation process attempts to create individual JSON files
    for each schema definition, including `Option<()>`. However, the
    characters `<` and `>` are invalid in Windows filenames, causing the
    file creation to fail.
    
    ## Solution
    
    The fix extends the existing `IGNORED_DEFINITIONS` constant (which was
    already being used in the **bundle generation**) to also skip
    `Option<()>` when generating individual JSON schema files. This
    maintains consistency with the existing behavior where `Option<()>` is
    excluded from the bundled schema.
    
    ---
    
    close #7479
  • Improved runtime of generated_ts_has_no_optional_nullable_fields test (#6851)
    The `generated_ts_has_no_optional_nullable_fields` test was occasionally
    failing on slow CI nodes because of a timeout. This change reduces the
    work done by the test. It adds some "options" for the `generate_ts`
    function so it can skip work that's not needed for the test.
  • Prompt to turn on windows sandbox when auto mode selected. (#6618)
    - stop prompting users to install WSL 
    - prompt users to turn on Windows sandbox when auto mode requested.
    
    <img width="1660" height="195" alt="Screenshot 2025-11-17 110612"
    src="https://github.com/user-attachments/assets/c67fc239-a227-417e-94bb-599a8ed8f11e"
    />
    <img width="1684" height="168" alt="Screenshot 2025-11-17 110637"
    src="https://github.com/user-attachments/assets/d18c3370-830d-4971-8746-04757ae2f709"
    />
    <img width="1655" height="293" alt="Screenshot 2025-11-17 110719"
    src="https://github.com/user-attachments/assets/d21f6ce9-c23e-4842-baf6-8938b77c16db"
    />
  • [app-server] small fixes for JSON schema export and one-of types (#6614)
    A partner is consuming our generated JSON schema bundle for app-server
    and identified a few issues:
    - not all polymorphic / one-of types have a type descriminator
    - `"$ref": "#/definitions/v2/SandboxPolicy"` is missing
    - "Option<>" is an invalid schema name, and also unnecessary
    
    This PR:
    - adds the type descriminator to the various types that are missing it
    except for `SessionSource` and `SubAgentSource` because they are
    serialized to disk (adding this would break backwards compat for
    resume), and they should not be necessary to consume for an integration
    with app-server.
    - removes the special handling in `export.rs` of various types like
    SandboxPolicy, which turned out to be unnecessary and incorrect
    - filters out `Option<>` which was auto-generated for request params
    that don't need a body
    
    For context, we currently pull in wayyy more types than we need through
    the `EventMsg` god object which we are **not** planning to expose in API
    v2 (this is how I suspect `SessionSource` and `SubAgentSource` are being
    pulled in). But until we have all the necessary v2 notifications in
    place that will allow us to remove `EventMsg`, we will keep exporting it
    for now.
  • [app-server] feat: add command to generate json schema (#6406)
    Add a `codex generate-json-schema` command for generating a JSON schema
    bundle of app-server types, analogous to the existing `codex
    generate-ts` command for Typescript.
  • [app-server] feat: export.rs supports a v2 namespace, initial v2 notifications (#6212)
    **Typescript and JSON schema exports**
    While working on Thread/Turn/Items type definitions, I realize we will
    run into name conflicts between v1 and v2 APIs (e.g. `RateLimitWindow`
    which won't be reusable since v1 uses `RateLimitWindow` from `protocol/`
    which uses snake_case, but we want to expose camelCase everywhere, so
    we'll define a V2 version of that struct that serializes as camelCase).
    
    To set us up for a clean and isolated v2 API, generate types into a
    `v2/` namespace for both typescript and JSON schema.
    - TypeScript: v2 types emit under `out_dir/v2/*.ts`, and root index.ts
    now re-exports them via `export * as v2 from "./v2"`;.
    - JSON Schemas: v2 definitions bundle under `#/definitions/v2/*` rather
    than the root.
    
    The location for the original types (v1 and types pulled from
    `protocol/` and other core crates) haven't changed and are still at the
    root. This is for backwards compatibility: no breaking changes to
    existing usages of v1 APIs and types.
    
    **Notifications**
    While working on export.rs, I:
    - refactored server/client notifications with macros (like we already do
    for methods) so they also get exported (I noticed they weren't being
    exported at all).
    - removed the hardcoded list of types to export as JSON schema by
    leveraging the existing macros instead
    - and took a stab at API V2 notifications. These aren't wired up yet,
    and I expect to iterate on these this week.
  • [App-server] v2 for account/updated and account/logout (#6175)
    V2 for `account/updated` and `account/logout` for app server. correspond
    to old `authStatusChange` and `LogoutChatGpt` respectively. Followup PRs
    will make other v2 endpoints call `account/updated` instead of
    `authStatusChange` too.
  • [app-server] remove serde(skip_serializing_if = "Option::is_none") annotations (#5939)
    We had this annotation everywhere in app-server APIs which made it so
    that fields get serialized as `field?: T`, meaning if the field as
    `None` we would omit the field in the payload. Removing this annotation
    changes it so that we return `field: T | null` instead, which makes
    codex app-server's API more aligned with the convention of public OpenAI
    APIs like Responses.
    
    Separately, remove the `#[ts(optional_fields = nullable)]` annotations
    that were recently added which made all the TS types become `field?: T |
    null` which is not great since clients need to handle undefined and
    null.
    
    I think generally it'll be best to have optional types be either:
    - `field: T | null` (preferred, aligned with public OpenAI APIs)
    - `field?: T` where we have to, such as types generated from the MCP
    schema:
    https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/2025-06-18/schema.ts
    (see changes to `mcp-types/`)
    
    I updated @etraut-openai's unit test to check that all generated TS
    types are one or the other, not both (so will error if we have a type
    that has `field?: T | null`). I don't think there's currently a good use
    case for that - but we can always revisit.
  • Add missing "nullable" macro to protocol structs that contain optional fields (#5901)
    This PR addresses a current hole in the TypeScript code generation for
    the API server protocol. Fields that are marked as "Optional<>" in the
    Rust code are serialized such that the value is omitted when it is
    deserialized — appearing as `undefined`, but the TS type indicates
    (incorrectly) that it is always defined but possibly `null`. This can
    lead to subtle errors that the TypeScript compiler doesn't catch. The
    fix is to include the `#[ts(optional_fields = nullable)]` macro for all
    protocol structs that contain one or more `Optional<>` fields.
    
    This PR also includes a new test that validates that all TS protocol
    code containing "| null" in its type is marked optional ("?") to catch
    cases where `#[ts(optional_fields = nullable)]` is omitted.
  • [app-server] Annotate more exported types with a title (#5879)
    Follow-up to https://github.com/openai/codex/pull/5063
    
    Refined the app-server export pipeline so JSON Schema variants and
    discriminator fields are annotated with descriptive, stable titles
    before writing the bundle. This eliminates anonymous enum names in the
    generated Pydantic models (goodbye Type7) while keeping downstream
    tooling simple. Added shared helpers to derive titles and literals, and
    reused them across the traversal logic for clarity. Running just fix -p
    codex-app-server-protocol, just fmt, and cargo test -p
    codex-app-server-protocol validates the change.
  • fix: revert "[app-server] fix account/read response annotation (#5642)" (#5796)
    Revert #5642 because this generates:
    
    ```
    // GENERATED CODE! DO NOT MODIFY BY HAND!
    
    // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
    
    export type GetAccountResponse = Account | null;
    ```
    
    But `Account` is unknown.
    
    The unique use of `#[ts(export)]` on `GetAccountResponse` is also
    suspicious as are the changes to
    `codex-rs/app-server-protocol/src/export.rs` since the existing system
    has worked fine for quite some time.
    
    Though a pure backout of #5642 puts things in a state where, as the PR
    noted, the following does not work:
    
    ```
    cargo run -p codex-app-server-protocol --bin export -- --out DIR
    ```
    
    So in addition to the backout, this PR adds:
    
    ```rust
    #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
    #[serde(rename_all = "camelCase")]
    pub struct GetAccountResponse {
        pub account: Account,
    }
    ```
    
    and changes `GetAccount.response` as follows:
    
    ```diff
    -        response: Option<Account>,
    +        response: GetAccountResponse,
    ```
    
    making it consistent with other types.
    
    With this change, I verified that both of the following work:
    
    ```
    just codex generate-ts --out /tmp/somewhere
    cargo run -p codex-app-server-protocol --bin export -- --out /tmp/somewhere-else
    ```
    
    The generated TypeScript is as follows:
    
    ```typescript
    // GetAccountResponse.ts
    import type { Account } from "./Account";
    
    export type GetAccountResponse = { account: Account, };
    ```
    
    and
    
    ```typescript
    // Account.ts
    import type { PlanType } from "./PlanType";
    
    export type Account = { "type": "ApiKey", api_key: string, } | { "type": "chatgpt", email: string | null, plan_type: PlanType, };
    ```
    
    Though while the inconsistency between `"type": "ApiKey"` and `"type":
    "chatgpt"` is quite concerning, I'm not sure if that format is ever
    written to disk in any case, but @owenlin0, I would recommend looking
    into that.
    
    Also, it appears that the types in `codex-rs/protocol/src/account.rs`
    are used exclusively by the `app-server-protocol` crate, so perhaps they
    should just be moved there?
  • [app-server] fix account/read response annotation (#5642)
    The API schema export is currently broken:
    ```
    > cargo run -p codex-app-server-protocol --bin export -- --out DIR
    Error: this type cannot be exported
    ```
    
    This PR fixes the error message so we get more info:
    ```
    > cargo run -p codex-app-server-protocol --bin export -- --out DIR
    Error: failed to export client responses: dependency core::option::Option<codex_protocol::account::Account> cannot be exported
    ```
    
    And fixes the root cause which is the `account/read` response.
  • Generate JSON schema for app-server protocol (#5063)
    Add annotations and an export script that let us generate app-server
    protocol types as typescript and JSONSchema.
    
    The script itself is a bit hacky because we need to manually label some
    of the types. Unfortunately it seems that enum variants don't get good
    names by default and end up with something like `EventMsg1`,
    `EventMsg2`, etc. I'm not an expert in this by any means, but since this
    is only run manually and we already need to enumerate the types required
    to describe the protocol, it didn't seem that much worse. An ideal
    solution here would be to have some kind of root that we could generate
    schemas for in one go, but I'm not sure if that's compatible with how we
    generate the protocol today.