Commit Graph
17 Commits
Author SHA1 Message Date
Daniel Wolf 5157493c23 Expose onboarding hints in login completion notifications (#36635)
## What changed

- Accept the allowlisted `.onboarding_entrypoint=life_sciences` suffix on a valid OAuth state while continuing to reject unknown or malformed suffixes.
- Return the parsed callback metadata from the login server without including the suffix in the token exchange redirect URI.
- Add the optional `onboardingEntrypoint` field and `life_sciences` value to the v2 `account/login/completed` notification and generated protocol exports.

## Testing

- Cover valid, invalid, and repeated OAuth state suffixes.
- Verify the end-to-end login callback result, token redirect URI, and app-server notification payload.

GitOrigin-RevId: c2ee146328ddd43c03a503260d5d492e186fa889
2026-08-02 21:01:04 +00:00
Michael Bolin acd540f158 Precompute app-server protocol exports (#36212)
## Why

Normal app-server protocol builds do not need the `ts-rs` and `schemars`
implementations used to generate schema exports.

## What changed

- Embed compressed stable and experimental TypeScript and JSON schema exports,
  and serve the existing export APIs from those artifacts.
- Use no-op schema derives in non-test builds while keeping the real generators
  available for fixture regeneration and tests.
- Move schema fixture regeneration behind a Python helper and update
  `just write-app-server-schema --experimental` to refresh the experimental
  embedded exports.

## Testing

- Verify embedded exports match freshly generated stable and experimental
  schemas.
- Verify export options and on-disk output remain compatible.

GitOrigin-RevId: e8536338b457e6eec34bdf29ec0684144bd13734
2026-07-30 19:47:30 +00:00
joeytrasatti-openai ad6fc66b6d Add persisted manual ordering for thread sections (#36007)
## What changed

- Add `thread/section/move` to atomically move a thread into, within, or out of a section. Threads can be inserted before an existing member or appended, and moves within a section preserve `sectionEnteredAt`.
- Add `section_position` sorting to `thread/list`, with ascending order as its default, and expose `sectionEnteredAt` in thread responses.
- Persist section positions and entry times in SQLite, including migration of existing section members into recency order. Section membership is no longer updated through `thread/metadata/update`.

## Testing

- Cover section moves, reordering, pagination, persistence across restarts and rollout reconciliation, concurrent updates, and rank renumbering.

GitOrigin-RevId: aec6d7ddedca5277029b5caf5c074975397e956c
2026-07-29 18:37:22 +00:00
Celia Chen 315195492c Support custom transports for Amazon Bedrock (#33695)
## What changed

- Allow the built-in `amazon-bedrock` provider to override `base_url`, `auth`,
  and `http_headers` in addition to its AWS profile and region.
- Use command-based bearer authentication and configured endpoints without
  applying AWS request signing, while retaining regional endpoint resolution
  for the default Bedrock configuration.
- Replace the Bedrock account `credentialSource` enum with the
  `usesCodexManagedCredentials` boolean so command-authenticated and other
  externally managed configurations are reported consistently.

## Testing

- Cover configuration merging and validation, command-authenticated proxy
  requests with custom headers, and account reporting for managed and external
  credentials.

GitOrigin-RevId: d1acbe602060470583b5e12f8d304bee5be46f4c
2026-07-16 21:41:00 +00:00
stefanstokic-oai 4df8027a97 Honor workspace spend controls in rate-limit handling (#33187)
## Why

Sparse and out-of-order rate-limit updates can omit account metadata or let an
older full read overwrite a newer workspace hard stop. Credit availability also
does not always include a displayable balance.

## What changed

- Propagate the backend's `spendControlReached` state through rate-limit
  snapshots and the app-server protocol, preserving it across sparse updates.
- Keep workspace hard-stop classifications for error routing and ignore stale
  full-read results after a newer hard-stop notification.
- Base TUI warnings and model-switch prompts on credit availability and hard-stop
  state, and show `Credits: Available` when a finite balance is hidden.

## Testing

Added coverage for spend-control mapping, snapshot merging, out-of-order reads,
workspace error routing, warning and prompt behavior, and credit status display.

GitOrigin-RevId: 18b09d493d5a620a7c079fb721ec50b38dd5b04c
2026-07-14 22:43:26 +00:00
Celia Chen b45fef0774 feat: add managed Bedrock login API (#31327)
## Why

App-server clients can report whether Amazon Bedrock is using
AWS-managed credentials or a Codex-managed API key, but they do not have
a matching API for creating the managed login. This PR defines that
experimental wire contract independently from its implementation.

Managed Bedrock API keys are already a primary `CodexAuth` mode. The API
therefore describes a normal Codex login that replaces the current
stored auth rather than introducing provider-scoped credential storage.

## What changed

- Add the experimental `amazonBedrock` variant to `account/login/start`.
- Accept an API key and AWS region and return a matching discriminated
response.
- Gate the request behind the app-server `experimentalApi` capability.
- Regenerate the JSON and TypeScript protocol schemas.
- Document the login contract, notifications, primary-auth replacement
semantics, restart boundary, and non-transactional durable writes.

## Impact

This PR defines the API shape but does not implement login behavior. The
next PR adds validation, persistence through the existing Codex auth
lifecycle, provider selection, and notifications.

## Validation

- `just test -p codex-app-server-protocol`

## Stack

1. **#31327 Managed Bedrock experimental API** — base: `main`
2. #31326 Managed Bedrock login — base: `codex/managed-bedrock-api`
3. #31325 Managed Bedrock logout — base:
`codex/managed-bedrock-login-v2`
2026-07-09 17:05:37 -07:00
rafael-jac 1fd0858e86 [login] support hosted success redirects (#28745)
## What

Adds an optional hosted login-success redirect path for app-server login
requests.

- Keeps the existing localhost success page as the default.
- Lets app-server callers opt into a hosted success page with an
optional protocol field.
- Persists credentials before redirecting to the hosted success page.
- Keeps org setup and existing CLI/device-code login flows on the local
success page.
- Accepts an optional typed `appBrand` value and forwards it to the
hosted page as `app_brand` so web can select the correct asset.
- Generates the app-server protocol schema updates for the new optional
fields.

## Why

This supports the hosted Codex login success page rollout without
changing existing login behavior by default. The Codex Apps frontend can
gate the opt-in with Statsig after the hosted web page.

## Rollout safety

- Old callers omit the new field and continue using localhost.
- New callers talking to old app-server builds remain safe because the
Codex Apps side treats the field as optional and defaults the flag off.
- Missing brand values default to Codex.
- The hosted redirect always uses the app-login source so the hosted
page can reopen Codex; the existing streamlined-login visual flag
remains separate.

## Validation

- `just fmt`
- `just fix -p codex-login -p codex-app-server-protocol -p
codex-app-server -p codex-app-server-test-client -p codex-tui`
- `just test -p codex-login`
- `just test -p codex-app-server-protocol`
- `just write-app-server-schema`
- `git diff HEAD --check`

The focused login and protocol run passed all 380 tests.

I also started the broader `just test -p codex-app-server`; it compiled
successfully, then many tests failed on this machine because spawned
test servers tried to use the ambient `/Users/rafaelj/.codex/sqlite`
state DB, which is read-only in this sandbox. I stopped that run after
confirming the failures shared that environment issue.
2026-07-07 19:48:05 +00:00
jay 58ec528315 [app-server] Include reset-credit details in rate limits (#30395)
## Why

Supported clients currently receive only a reset-credit count from
`account/rateLimits/read`. The redemption UI and other app-server
clients need each available credit's expiry and ID so they can explain
what will expire and consume the credit a user selected. This
information belongs on the existing rate-limit read surface rather than
a second app-server list RPC that clients would need to coordinate.

## What changed

- extend `rateLimitResetCredits` on `account/rateLimits/read` with
nullable `credits` detail rows
- fetch usage and reset-credit details concurrently; if the detail
request fails, times out, or cannot be parsed, preserve the usage
response and return `credits: null`
- expose each credit's ID, reset type, status, grant time, expiry time,
title, and description
- add an optional nullable `creditId` to
`account/rateLimitResetCredit/consume`; omitting it preserves the
existing automatic-selection behavior
- forward a selected credit ID to the Codex backend and update the
app-server documentation and generated schemas

The TUI consumer is stacked in #30488.

## Validation

- `just test -p codex-app-server-protocol` (251 passed)
- `just test -p codex-backend-client` (16 passed)
- `just test -p codex-app-server rate_limit` (18 passed)

Part of #29618.
2026-07-06 12:54:06 -07:00
efrazer-oai 5a67d898a5 Allow ChatGPT accounts without email (#28991)
# Summary

Codex required every ChatGPT account to have an email address. A
service-account personal access token can return valid account metadata
without one, so PAT login failed while decoding the metadata response.

This change makes email optional in the account metadata type that owns
it and preserves that absence through authentication, provider account
state, the app-server API, generated clients, and TUI bootstrap.
Existing accounts with email addresses keep the same behavior.

## Behavior-changing call sites

| Call site | Behavior after this change |
| --- | --- |
| `login/src/auth/personal_access_token.rs` | PAT metadata accepts a
missing or null email and retains `None`. |
| `agent-identity/src/lib.rs` | Agent Identity JWT claims accept an
omitted email. |
| `login/src/auth/storage.rs` and `login/src/auth/agent_identity.rs` |
Stored and managed Agent Identity records carry `Option<String>`.
Deserialization maps the legacy empty-string sentinel to `None`. |
| `login/src/auth/manager.rs` | `get_account_email` returns the stored
option, and managed identity bootstrap no longer converts `None` to an
empty string. |
| `model-provider/src/provider.rs` and `protocol/src/account.rs` | A
ChatGPT provider account requires a plan type but may carry no email. |
| `app-server-protocol/src/protocol/v2/account.rs` | `account/read`
keeps the `email` field on the wire and returns `null` when the account
has no email. Generated TypeScript and JSON schemas describe a required,
nullable field. |
| `sdk/python/src/openai_codex/generated/v2_all.py` | The generated
Python `ChatgptAccount` model accepts `None` for email. |
| `tui/src/app_server_session.rs` | Email-less ChatGPT accounts
bootstrap normally, keep external feedback routing, omit account-email
telemetry, and display the plan in account status. |

## Design decisions

- Missing email remains `None` at every layer. The code never uses an
empty string as a substitute.
- The app-server response includes `"email": null` instead of omitting
the field. Clients retain a stable response shape.
- Plan type remains required for provider account state. This change
relaxes only the email assumption.

## Testing

Tests: affected test targets compile, scoped Clippy and formatting pass,
a focused TUI snapshot covers plan-only account status, real
before/after PAT login smoke covers metadata without email, app-server
smoke covers `account/read` with `email: null`, and a regression smoke
covers an existing email-bearing PAT. Unit tests run in CI.

## Evidence

Visual smoke evidence will be attached here.
2026-06-22 13:19:40 -07:00
xli-oai 21d36296f1 Add workspace messages app-server API (#29001)
## Summary

- Add backend-client types and fetch support for active workspace
messages.
- Add the app-server v2 `account/workspaceMessages/read` method,
generated schemas, and README documentation.
- Delegate workspace-message eligibility to the Codex backend feature
gate; map a backend 404 to `featureEnabled: false`.

## Testing

- `just write-app-server-schema`
- `just test -p codex-backend-client`
- `just test -p codex-app-server-protocol`
- `just test -p codex-app-server workspace_messages`
- `just fix -p codex-backend-client -p codex-app-server-protocol -p
codex-app-server`
- `just fmt`

## Stack

- Base PR for #28232, which adds the TUI status-line integration.
2026-06-22 04:25:07 -07:00
Celia Chen 12aaeb7bf8 [codex] expose Bedrock credential source in account/read (#27751)
## Why

`account/read` currently reports only `type: "amazonBedrock"`, so
clients cannot distinguish a Codex-managed Bedrock API key from
credentials supplied by AWS. The app UI needs that distinction to render
the appropriate account state without duplicating provider-auth logic.

Credential-source selection belongs to the Bedrock model provider
because it already owns the precedence between managed Bedrock auth and
the external AWS credential path. This builds on #27443 and #27689.

## What changed

- Added `AmazonBedrockCredentialSource` with `codexManaged` and
`awsManaged` values.
- Included the selected credential source in
`ProviderAccount::AmazonBedrock` and the app-server `Account` response.
- Made `AmazonBedrockModelProvider::account_state()` classify the source
from its managed-auth state.
- Regenerated the app-server JSON and TypeScript schemas.
- Updated app-server account documentation and downstream TUI matches.

`codexManaged` means the provider found a managed Bedrock API key.
`awsManaged` identifies the provider's external AWS credential path; it
does not assert that the AWS credential chain has been validated.

## Testing

- Added model-provider coverage for Codex-managed precedence and
AWS-managed fallback.
- Added app-server protocol serialization coverage for both wire values.
- Added app-server integration coverage for both `account/read`
responses.
- `just test -p codex-protocol -p codex-model-provider -p
codex-app-server-protocol` (497 tests passed).

After rebasing onto #27711, the `codex-app-server` test target compiled
past the image-generation `PathUri` migration. Local linking was then
interrupted by disk exhaustion (`No space left on device`).
2026-06-16 07:14:53 +00:00
jay bef99f861b feat(app-server): expose rate-limit reset credits (#28143)
## Why

Codex users can earn personal rate-limit reset credits, but app-server
clients do not currently have an API for reading or redeeming them. This
adds the backend and protocol foundation used by the `/usage` TUI flow
in #28154.

## What changed

- Extend `account/rateLimits/read` with a nullable
`rateLimitResetCredits` summary sourced from the existing usage
response.
- Add backend-client and app-server support for consuming a reset with a
caller-generated idempotency key. A UUID is recommended, and clients
reuse the same key when retrying the same logical reset.
- Return only the consume `outcome`; clients refetch
`account/rateLimits/read` for updated window state.
- Document the response field and each consume outcome, and regenerate
the JSON and TypeScript schema fixtures.
- Clarify in `AGENTS.md` that new app-server string enum values use
camelCase on the wire.
- Update the existing TUI response fixture for the expanded protocol
shape.
- Add coverage for authentication, response mapping, backend failures,
consume outcomes, and request timeout behavior.

## Validation

- `just test -p codex-app-server-protocol` — 231 passed.
- `just test -p codex-backend-client` — 14 passed.
- Focused `codex-app-server` reset-credit tests — 5 passed.
- Focused `codex-tui` protocol response fixture test — passed.
- `just fix -p codex-backend-client -p codex-app-server-protocol -p
codex-app-server` — passed.
- `just fmt` — passed.
2026-06-15 21:54:01 +00:00
Felipe Coury 5e62c735b2 feat(app-server): expose account token usage [1 of 2] (#25344)
## Why

Token activity is useful account-level context, but terminal clients
need a supported app-server path to fetch it without reaching into
ChatGPT backend details directly. The API should also live under the
broader account usage umbrella so future usage surfaces can be added
without proliferating user-facing concepts.

## What Changed

- Add `codex-backend-client` support for the ChatGPT profile token-usage
payload.
- Add the v2 `account/usage/read` app-server RPC.
- Map lifetime usage, peak daily usage, streak, longest task duration,
and daily buckets into app-server protocol types.
- Gate the request on Codex-backend auth, which supports ChatGPT auth
tokens and AgentIdentity.
- Regenerate the app-server JSON and TypeScript schema fixtures.

## Token Count Source

`account/usage/read` returns the token-usage aggregate supplied by the
ChatGPT profile backend. App-server maps that backend-owned aggregate
into protocol fields; it does not recompute cached-token treatment,
usage multipliers, or raw input/output totals locally.

## Stack

1. feat(app-server): expose account token usage [1 of 2] (this PR)
2. [#25345](https://github.com/openai/codex/pull/25345) feat(tui): add
token activity command [2 of 2]

## How to Test

1. Start an app-server client from this branch while authenticated with
ChatGPT or AgentIdentity.
2. Call `account/usage/read`.
3. Confirm the response includes `summary` and `dailyUsageBuckets`.
4. Also verify a session without Codex-backend auth receives the
existing auth error path.

Targeted tests:
- `just test -p codex-backend-client -p codex-app-server-protocol -p
codex-app-server`
- `just write-app-server-schema`
2026-06-05 14:43:44 +00:00
dhruvgupta-oai a2ebe07b39 [profile-switcher][rust] -- [1/2] Add app-server account session protocol (#25469)
## Summary

Adds the app-server v2 `accountSession/*` protocol used by the Desktop
profile switcher and the backend account metadata client needed to
populate workspace choices.

This is the protocol layer only. The app-server lifecycle and
consolidated saved-session storage are split into a follow-up PR.

## Rust Stack

1. This PR
2. [openai/codex#25383](https://github.com/openai/codex/pull/25383) adds
app-server session lifecycle behavior and consolidated saved-session
storage.

## Validation

- Generated app-server schema fixtures are included from the existing
generation flow in the lifecycle PR where the routes are registered.
- Did not run tests per requested scope.
2026-06-04 01:25:11 +05:30
efrazer-oai c8e5db16c9 feat: show enterprise monthly credit limits in status (#24812)
## Summary

Enterprise users can have an effective monthly credit limit, but Codex
`/status` currently drops that metadata from the account-usage response.

This change adds the optional `spend_control.individual_limit`
projection to the existing rate-limit snapshot flow. The backend client
reads the monthly limit, app-server exposes it as `individualLimit`, and
the TUI renders a `Monthly credit limit` row through the existing
progress-bar renderer.

When the backend does not return an effective monthly limit, existing
rate-limit behavior is unchanged.

## Existing backend state

The account-usage backend already returns the effective monthly limit
and current usage together:

```json
{
  "spend_control": {
    "reached": false,
    "individual_limit": {
      "limit": "25000",
      "used": "8000",
      "remaining": "17000",
      "used_percent": 32,
      "remaining_percent": 68,
      "reset_after_seconds": 86400,
      "reset_at": 1778137680
    }
  }
}
```

Before this change, Codex projected rolling `primary` and `secondary`
windows plus `credits`. It ignored `spend_control.individual_limit`, so
app-server clients and `/status` could not render the monthly cap.

The updated flow is:

```text
account usage backend
  -> backend-client reads spend_control.individual_limit
  -> existing rate-limit snapshot carries optional individual_limit
  -> app-server exposes optional individualLimit
  -> TUI renders Monthly credit limit
```

## App-server contract

`account/rateLimits/read` and sparse `account/rateLimits/updated`
notifications now include an additive nullable
`rateLimits.individualLimit` field:

```json
{
  "individualLimit": {
    "limit": "25000",
    "used": "8000",
    "remainingPercent": 68,
    "resetsAt": 1778137680
  }
}
```

In an `account/rateLimits/read` response, `null` means no monthly limit
is available. `account/rateLimits/updated` remains a sparse rolling
notification: clients merge available values into their most recent
`account/rateLimits/read` snapshot or refetch. Nullable account metadata
in a rolling notification does not clear a previously observed value.

## Design decisions

- Extend the existing rate-limit snapshot instead of introducing a
separate request or wire-level update protocol.
- Keep the Codex projection narrow: `/status` needs the effective limit,
current usage, remaining percentage, and reset timestamp.
- Render the monthly row through the existing progress-bar renderer,
with one optional detail line for `8,000 of 25,000 credits used`.
- Keep the backend response optional so existing accounts and older
usage states preserve their current behavior.
- Preserve cached monthly metadata when sparse rolling notifications
omit it. Live account-usage reads remain authoritative and can clear a
removed limit.

## Visual evidence

```text
 Monthly credit limit:   [██████████████░░░░░░] 68% left (resets 07:08 on 7 May)
                         8,000 of 25,000 credits used
```

Snapshot:
`codex-rs/tui/src/status/snapshots/codex_tui__status__tests__status_snapshot_includes_enterprise_monthly_credit_limit.snap`

## Testing

Tests: generated app-server schema verification, protocol tests,
backend-client tests, app-server integration coverage, TUI snapshot
coverage, formatting, and workspace lint cleanup.
2026-06-01 21:25:42 -07:00
Owen Lin cff960896c fix(app-server): fix optional bool annotations (#24099)
`#[serde(default)]` wasn't sufficient for our generated TS types to
reflect that clients didn't have to set them. We also need
`skip_serializing_if = "std::ops::Not::not"`. This is already a rule in
our agents.md file.
2026-05-22 16:52:53 +00:00
Owen Lin d7de4dd3ac chore(app-server-protocol): split v2 API definitions into modules (#21251)
## Why

`codex-rs/app-server-protocol/src/protocol/v2.rs` had grown into a
single ~12k-line definition file for the entire app-server v2 API.

This is purely a mechanical refactor to break up the monolithic `v2.rs`
file that contains all app-server API v2 types into more modular files,
grouped by resource (e.g. account, thread, turn, etc.).

`just write-app-server-schema` shows no real changes, so we can be sure
that this is purely an internal organizational change.

## What changed

- Replaced the monolithic `protocol/v2.rs` with a `protocol/v2/` module
tree and a small `mod.rs` that only declares and reexports modules.
- Grouped v2 API definitions by conceptual owner, including `account`,
`apps`, `collaboration_mode`, `command_exec`, `config`, `device_key`,
`experimental_feature`, `feedback`, `fs`, `hook`, `item`, `mcp`,
`model`, `notification`, `permissions`, `plugin`, `process`, `realtime`,
`review`, `thread`, `thread_data`, `turn`, and `windows_sandbox`.
- Moved v2 tests into `protocol/v2/tests.rs` so `mod.rs` stays small.
- Kept shared protocol helpers in `protocol/v2/shared.rs`, including the
enum mirroring macro and common cross-resource types.
- Co-located resource-specific notifications and server-request payloads
with the modules that own those resources.
- Regenerated app-server protocol schema fixtures. The schema diffs are
non-semantic newline-only changes after the refactor.

## Verification

- `cargo check -p codex-app-server-protocol`
- `cargo test -p codex-app-server-protocol`
- `just write-app-server-schema`
2026-05-05 16:46:51 -07:00