Commit Graph

15 Commits

  • feat: add Bedrock API key as a managed auth mode (#27443)
    ## Why
    
    Codex needs to manage Amazon Bedrock API key credentials through the
    existing auth lifecycle instead of introducing a separate auth manager
    or provider-specific credential file. Treating Bedrock API key login as
    a primary auth mode gives it the same persistence, keyring, reload, and
    logout behavior as the existing OpenAI API key and ChatGPT modes.
    
    The credential is valid only for the `amazon-bedrock` model provider.
    OpenAI-compatible providers must reject this auth mode rather than
    treating the Bedrock key as an OpenAI bearer token.
    
    ## What changed
    
    - Added `bedrockApiKey` as an app-server `AuthMode` and
    `CodexAuth::BedrockApiKey` as a primary `AuthManager` mode.
    - Added `BedrockApiKeyAuth`, containing the API key and AWS region, to
    the existing `AuthDotJson` payload stored in `$CODEX_HOME/auth.json` or
    the configured keyring backend.
    - Added `login_with_bedrock_api_key(...)`, parallel to
    `login_with_api_key(...)`, which replaces the current stored login with
    Bedrock credentials.
    - Reused generic auth reload and logout behavior instead of adding a
    Bedrock-specific auth manager or logout path.
    - Updated login restrictions, status reporting, diagnostics, telemetry
    classification, generated app-server schemas, and auth fixtures for the
    new mode.
    - Added explicit errors when Bedrock API key auth is selected with an
    OpenAI-compatible model provider.
    
    This PR establishes managed storage and auth-mode behavior. Routing the
    managed key and region into Amazon Bedrock requests will be in follow-up
    PRs.
  • [codex-rs] support v2 personal access tokens (#25731)
    ## Summary
    
    - add v2 personal access token support for `codex login
    --with-access-token` and `CODEX_ACCESS_TOKEN`
    - classify opaque `at-` tokens separately from legacy Agent Identity
    JWTs
    - hydrate required ChatGPT account metadata through AuthAPI
    `/v1/user-auth-credential/whoami`
    - use PATs directly as bearer tokens while preserving existing ChatGPT
    account surfaces
    - expose PAT-backed auth as the explicit `personalAccessToken`
    app-server auth mode
    
    ## Implementation
    
    PAT auth is intentionally small and stateless. Loading a PAT performs
    one AuthAPI metadata request, stores the hydrated metadata in the
    in-memory auth object, and redacts the secret from debug output. Legacy
    Agent Identity JWT handling remains unchanged. The shared access-token
    classifier lives in a private neutral module because it dispatches
    between both credential types.
    
    PAT hydration fails closed when AuthAPI omits any required metadata,
    including email. Hydrated metadata is intentionally not persisted:
    startup performs a live `whoami` preflight so revoked tokens or changed
    account metadata are not accepted from a stale cache.
    
    ## Workspace restriction scope
    
    This change intentionally does **not** apply
    `forced_chatgpt_workspace_id` to PAT authentication. The setting is a
    client-side config guardrail, not an authorization boundary, and PAT
    does not currently require workspace-ID parity. The PAT login and
    `CODEX_ACCESS_TOKEN` paths therefore validate through AuthAPI without
    threading workspace-restriction state through access-token loading.
    Existing workspace checks for non-PAT auth remain on their established
    paths.
    
    ## App-server compatibility
    
    The public app-server `AuthMode` is shared across v1 and v2, and
    PAT-backed auth reports `personalAccessToken` through both APIs.
    Following human review, this intentionally removes the temporary v1
    compatibility mapping that reported PATs as `chatgpt`; the deprecated v1
    API is kept in parity with v2 rather than maintaining a separate closed
    enum. Clients with exhaustive auth-mode handling in either API version
    must add the new case and should generally treat it as ChatGPT-backed
    unless they need PAT-specific behavior.
    
    The v1 auth-status response still omits the raw PAT when `includeToken`
    is requested because that response cannot carry the account metadata
    needed to reuse the credential safely. Persisted PAT auth also omits the
    new enum value so older Codex builds can deserialize `auth.json` and
    infer PAT auth from the credential field after a rollback.
    
    ## Validation
    
    Latest review-fix validation:
    
    - `CARGO_INCREMENTAL=0 just test -p codex-login` (126 passed)
    - `CARGO_INCREMENTAL=0 just test -p codex-cli` (263 passed)
    - `CARGO_INCREMENTAL=0 just test -p codex-cli
    stored_auth_validation_handles_personal_access_token`
    - `CARGO_INCREMENTAL=0 just test -p codex-app-server-protocol` (226
    passed)
    - `CARGO_INCREMENTAL=0 just test -p codex-models-manager
    refresh_available_models_uses_remote_only_catalog_for_chatgpt_auth`
    - `CARGO_INCREMENTAL=0 just test -p codex-tui
    existing_non_oauth_chatgpt_login_counts_as_signed_in`
    - `CARGO_INCREMENTAL=0 just fix -p codex-login -p
    codex-app-server-protocol -p codex-models-manager -p codex-tui -p
    codex-cli`
    - `just fmt`
    - `git diff --check`
    
    The broader `codex-tui` suite previously compiled and ran 2,834 tests.
    Three unrelated environment-sensitive guardian/IDE-socket tests failed
    after retries; the PAT-relevant TUI coverage passed.
  • Prefer the model list fetched from the backend for SIWC users (#22547)
    ## Summary
    - For SIWC users, update the model list merging logic to prefer the
    model list fetched from the backend over the bundled model list (this is
    needed for special cases where users have a more limited set of models
    they're allowed to use)
    - Add or update tests covering the revised cache behavior
    
    ## Testing
    - Added/updated unit tests in
    `codex-rs/models-manager/src/manager_tests.rs`
    - Not run (not requested)
  • [codex] Dedupe fallback model metadata warnings (#21090)
    Fixes #21070.
    
    This is a small cleanup around model metadata handling for
    gateway/provider model names. It follows the report and proposed
    direction from @dkbush by keeping the fallback metadata warning useful
    without repeating it every turn, and by tightening the existing
    provider-prefix lookup path.
    
    - Track fallback metadata warning slugs in session state so each
    unresolved model warns once per session.
    - Keep warning emission outside the session-state lock and preserve the
    existing warning text.
    - Allow one-segment provider prefixes with hyphenated provider IDs,
    while preserving the multi-segment rejection behavior.
    - Add focused coverage for warning dedupe and hyphenated provider-prefix
    metadata matching.
    
    Testing:
    
    - Ran `just fmt`.
    - Ran `git diff --check`.
    - Added tests for the new warning dedupe and provider-prefix lookup
    behavior.
  • Reduce the surface of collaboration modes (#20149)
    Collaboration modes were slightly invasive both into ThreadManager
    construction and ModelProvider
  • refactor: load agent identity runtime eagerly (#19763)
    ## Summary
    
    AgentIdentity auth previously registered the process task lazily behind
    a `OnceCell`. That meant the auth object could be constructed before its
    runtime task binding was known.
    
    This PR makes AgentIdentity auth load the runtime task at auth load time
    and stores the resulting process task id directly on the auth object.
    The model-provider call path can then read a concrete task id instead of
    handling a missing lazy value.
    
    ## Stack
    
    1. [refactor: make auth loading
    async](https://github.com/openai/codex/pull/19762) (merged)
    2. **This PR:** [refactor: load AgentIdentity runtime
    eagerly](https://github.com/openai/codex/pull/19763)
    3. [fix: configure AgentIdentity AuthAPI base
    URL](https://github.com/openai/codex/pull/19904)
    4. [feat: verify AgentIdentity JWTs with
    JWKS](https://github.com/openai/codex/pull/19764)
    
    ## Important call sites
    
    | Area | Change |
    | --- | --- |
    | `AgentIdentityAuth::load` | Registers the process task during auth
    loading and stores `process_task_id`. |
    | `CodexAuth::from_agent_identity_jwt` | Awaits AgentIdentity auth
    loading. |
    | model-provider auth | Reads a concrete `process_task_id` instead of an
    optional lazy value. |
    | AgentIdentity auth tests | Mock task registration now covers eager
    runtime allocation. |
    
    ## Design decisions
    
    AgentIdentity auth now treats task registration as part of constructing
    a usable auth object. That matches how callers use the value: once auth
    is present, the model-provider path expects the task-scoped assertion
    data to be ready.
    
    ## Testing
    
    Tests: targeted Rust auth test compilation, formatter, scoped Clippy
    fix, and Bazel lock check.
  • refactor: make auth loading async (#19762)
    ## Summary
    
    Auth loading used to expose synchronous construction helpers in several
    places even though some auth sources now need async work. This PR makes
    the auth-loading surface async and updates the callers to await it.
    
    This is intentionally only plumbing. It does not change how
    AgentIdentity tokens are decoded, how task runtime ids are allocated, or
    how JWT signatures are verified.
    
    ## Stack
    
    1. **This PR:** [refactor: make auth loading
    async](https://github.com/openai/codex/pull/19762)
    2. [refactor: load AgentIdentity runtime
    eagerly](https://github.com/openai/codex/pull/19763)
    3. [feat: verify AgentIdentity JWTs with
    JWKS](https://github.com/openai/codex/pull/19764)
    
    ## Important call sites
    
    | Area | Change |
    | --- | --- |
    | `codex-login` auth loading | `CodexAuth` and `AuthManager`
    construction paths now await auth loading. |
    | app-server startup | Auth manager construction is awaited during
    initialization. |
    | CLI/TUI/exec/MCP/chatgpt callers | Existing auth-loading calls now
    await the same behavior. |
    | cloud requirements storage loader | The loader becomes async so it can
    share the same auth construction path. |
    | auth tests | Tests that load auth now run in async contexts. |
    
    ## Testing
    
    Tests: targeted Rust auth test compilation, formatter, scoped Clippy
    fix, and Bazel lock check.
  • feat: let model providers own model discovery (#18950)
    ## Why
    
    `codex-models-manager` had grown to own provider-specific concerns:
    constructing OpenAI-compatible `/models` requests, resolving provider
    auth, emitting request telemetry, and deciding how provider catalogs
    should be sourced. That made the manager harder to reuse for providers
    whose model catalog is not fetched from the OpenAI `/models` endpoint,
    such as Amazon Bedrock.
    
    This change moves provider-specific model discovery behind
    provider-owned implementations, so the models manager can focus on
    refresh policy, cache behavior, picker ordering, and model metadata
    merging.
    
    ## What Changed
    
    - Introduced a `ModelsManager` trait with separate `OpenAiModelsManager`
    and `StaticModelsManager` implementations.
    - Added `ModelsEndpointClient` so OpenAI-compatible HTTP fetching lives
    outside `codex-models-manager`.
    - Moved `/models` request construction, provider auth resolution,
    timeout handling, and request telemetry into `codex-model-provider` via
    `OpenAiModelsEndpoint`.
    - Added provider-owned `models_manager(...)` construction so configured
    OpenAI-compatible providers use `OpenAiModelsManager`, while
    static/catalog-backed providers can return `StaticModelsManager`.
    - Added an Amazon Bedrock static model catalog for the GPT OSS Bedrock
    model IDs.
    - Updated core/session/thread manager code and tests to depend on
    `Arc<dyn ModelsManager>`.
    - Moved offline model test helpers into
    `codex_models_manager::test_support`.
    ## Metadata References
    
    The Bedrock catalog metadata is based on the official Amazon Bedrock
    OpenAI model documentation:
    
    - [Amazon Bedrock OpenAI
    models](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-openai.html)
    lists the Bedrock model IDs, text input/output modalities, and `128,000`
    token context window for `gpt-oss-20b` and `gpt-oss-120b`.
    - [Amazon Bedrock `gpt-oss-120b` model
    card](https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-openai-gpt-oss-120b.html)
    lists the `bedrock-runtime` model ID `openai.gpt-oss-120b-1:0`, the
    `bedrock-mantle` model ID `openai.gpt-oss-120b`, text-only modalities,
    and `128K` context window.
    - [OpenAI `gpt-oss-120b` model
    docs](https://developers.openai.com/api/docs/models/gpt-oss-120b)
    document configurable reasoning effort with `low`, `medium`, and `high`,
    plus text input/output modality.
    
    The display names, default reasoning effort, and priority ordering are
    Codex-local catalog choices.
    
    ## Test Plan
    - Manually verified app-server model listing with an AWS profile:
    
    ```shell
    CODEX_HOME="$(mktemp -d)" cargo run -p codex-app-server-test-client -- \
      --codex-bin ./target/debug/codex \
      -c 'model_provider="amazon-bedrock"' \
      -c 'model_providers.amazon-bedrock.aws.profile="codex-bedrock"' \
      -c 'model_providers.amazon-bedrock.aws.region="us-west-2"' \
      model-list
    ```
    
    The response returned the Bedrock catalog with `openai.gpt-oss-120b-1:0`
    as the default model and `openai.gpt-oss-20b-1:0` as the second listed
    model, both text-only and supporting low/medium/high reasoning effort.
  • feat: add explicit AgentIdentity auth mode (#18785)
    ## Summary
    
    This PR adds `CodexAuth::AgentIdentity` as an explicit auth mode.
    
    An AgentIdentity auth record is a standalone `auth.json` mode. When
    `AuthManager::auth().await` loads that mode, it registers one
    process-scoped task and stores it in runtime-only state on the auth
    value. Header creation stays synchronous after that because the task is
    initialized before callers receive the auth object.
    
    This PR also removes the old feature flag path. AgentIdentity is
    selected by explicit auth mode, not by a hidden flag or lazy mutation of
    ChatGPT auth records.
    
    Reference old stack: https://github.com/openai/codex/pull/17387/changes
    
    ## Design Decisions
    
    - AgentIdentity is a real auth enum variant because it can be the only
    credential in `auth.json`.
    - The process task is ephemeral runtime state. It is not serialized and
    is not stored in rollout/session data.
    - Account/user metadata needed by existing Codex backend checks lives on
    the AgentIdentity record for now.
    - `is_chatgpt_auth()` remains token-specific.
    - `uses_codex_backend()` is the broader predicate for ChatGPT-token auth
    and AgentIdentity auth.
    
    ## Stack
    
    1. https://github.com/openai/codex/pull/18757: full revert
    2. https://github.com/openai/codex/pull/18871: isolated Agent Identity
    crate
    3. This PR: explicit AgentIdentity auth mode and startup task allocation
    4. https://github.com/openai/codex/pull/18811: migrate Codex backend
    auth callsites through AuthProvider
    5. https://github.com/openai/codex/pull/18904: accept AgentIdentity JWTs
    and load `CODEX_AGENT_IDENTITY`
    
    ## Testing
    
    Tests: targeted Rust checks, cargo-shear, Bazel lock check, and CI.
  • feat: add a built-in Amazon Bedrock model provider (#18744)
    ## Why
    
    Codex needs a first-class `amazon-bedrock` model provider so users can
    select Bedrock without copying a full provider definition into
    `config.toml`. The provider has Codex-owned defaults for the pieces that
    should stay consistent across users: the display `name`, Bedrock
    `base_url`, and `wire_api`.
    
    At the same time, users still need a way to choose the AWS credential
    profile used by their local environment. This change makes
    `amazon-bedrock` a partially modifiable built-in provider: code owns the
    provider identity and endpoint defaults, while user config can set
    `model_providers.amazon-bedrock.aws.profile`.
    
    For example:
    
    ```toml
    model_provider = "amazon-bedrock"
    
    [model_providers.amazon-bedrock.aws]
    profile = "codex-bedrock"
    ```
    
    ## What Changed
    
    - Added `amazon-bedrock` to the built-in model provider map with:
      - `name = "Amazon Bedrock"`
      - `base_url = "https://bedrock-mantle.us-east-1.api.aws/v1"`
      - `wire_api = "responses"`
    - Added AWS provider auth config with a profile-only shape:
    `model_providers.<id>.aws.profile`.
    - Kept AWS auth config restricted to `amazon-bedrock`; custom providers
    that set `aws` are rejected.
    - Allowed `model_providers.amazon-bedrock` through reserved-provider
    validation so it can act as a partial override.
    - During config loading, only `aws.profile` is copied from the
    user-provided `amazon-bedrock` entry onto the built-in provider. Other
    Bedrock provider fields remain hard-coded by the built-in definition.
    - Updated the generated config schema for the new provider AWS profile
    config.
  • Add max context window model metadata (#18382)
    Adds max_context_window to model metadata and routes core context-window
    reads through resolved model info. Config model_context_window overrides
    are clamped to max_context_window when present; without an override, the
    model context_window is used.
  • Refactor config types into a separate crate (#16962)
    Move config types into a separate crate because their macros expand into
    a lot of new code.
  • remove temporary ownership re-exports (#16626)
    Stacked on #16508.
    
    This removes the temporary `codex-core` / `codex-login` re-export shims
    from the ownership split and rewrites callsites to import directly from
    `codex-model-provider-info`, `codex-models-manager`, `codex-api`,
    `codex-protocol`, `codex-feedback`, and `codex-response-debug-context`.
    
    No behavior change intended; this is the mechanical import cleanup layer
    split out from the ownership move.
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • extract models manager and related ownership from core (#16508)
    ## Summary
    - split `models-manager` out of `core` and add `ModelsManagerConfig`
    plus `Config::to_models_manager_config()` so model metadata paths stop
    depending on `core::Config`
    - move login-owned/auth-owned code out of `core` into `codex-login`,
    move model provider config into `codex-model-provider-info`, move API
    bridge mapping into `codex-api`, move protocol-owned types/impls into
    `codex-protocol`, and move response debug helpers into a dedicated
    `response-debug-context` crate
    - move feedback tag emission into `codex-feedback`, relocate tests to
    the crates that now own the code, and keep broad temporary re-exports so
    this PR avoids a giant import-only rewrite
    
    ## Major moves and decisions
    - created `codex-models-manager` as the owner for model
    cache/catalog/config/model info logic, including the new
    `ModelsManagerConfig` struct
    - created `codex-model-provider-info` as the owner for provider config
    parsing/defaults and kept temporary `codex-login`/`codex-core`
    re-exports for old import paths
    - moved `api_bridge` error mapping + `CoreAuthProvider` into
    `codex-api`, while `codex-login::api_bridge` temporarily re-exports
    those symbols and keeps the `auth_provider_from_auth` wrapper
    - moved `auth_env_telemetry` and `provider_auth` ownership to
    `codex-login`
    - moved `CodexErr` ownership to `codex-protocol::error`, plus
    `StreamOutput`, `bytes_to_string_smart`, and network policy helpers to
    protocol-owned modules
    - created `codex-response-debug-context` for
    `extract_response_debug_context`, `telemetry_transport_error_message`,
    and related response-debug plumbing instead of leaving that behavior in
    `core`
    - moved `FeedbackRequestTags`, `emit_feedback_request_tags`, and
    `emit_feedback_request_tags_with_auth_env` to `codex-feedback`
    - deferred removal of temporary re-exports and the mechanical import
    rewrites to a stacked follow-up PR so this PR stays reviewable
    
    ## Test moves
    - moved auth refresh coverage from `core/tests/suite/auth_refresh.rs` to
    `login/tests/suite/auth_refresh.rs`
    - moved text encoding coverage from
    `core/tests/suite/text_encoding_fix.rs` to
    `protocol/src/exec_output_tests.rs`
    - moved model info override coverage from
    `core/tests/suite/model_info_overrides.rs` to
    `models-manager/src/model_info_overrides_tests.rs`
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>