Repository navigation
Update ghcr.io/james-6-23/codex2api Docker tag to v3.1.1 - #7965
Open
renovate[bot] wants to merge 1 commit into
Open
renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
3.0.8→3.1.1Warning
Some dependencies could not be looked up. Check the Dependency Dashboard for more information.
Release Notes
james-6-23/codex2api (ghcr.io/james-6-23/codex2api)
v3.1.1Compare Source
Features
Accounts can be checked for degraded answers on a schedule (#790, @OneAHPro). The new Intelligence Check page (
/admin/intelligence-check) sends questions from an admin-maintained bank to a specific GPT/Codex, Responses relay or Claude account, manually or on an interval. Grok and Antigravity are not supported yet. Each question has an expected answer, matched exactly, by substring or by regex, and an optional latency limit. Checks reuse the account's request executor, identity, fingerprint and timezone, and go through the account's bound proxy only: they connect directly when none is bound and never fall back to direct when the bound proxy fails. A failed request is recorded as an error, separately from a wrong answer, and does not count toward the pass rate. After a configurable number of consecutive failures the account can be paused for dispatch or moved to another group, and it is restored once checks pass again. Only pauses and group changes made by the check are undone, and a manual change to the account cancels them. The account table, cards and details show the last 20 results next to the health bar, and a paged history (200 runs per account by default) keeps the question, judging config, final output and actions. Runs use a durable SQLite/PostgreSQL queue with leases, per-account deduplication and a shared concurrency limit. Automatic checks are off by default and existing accounts are opted out; new accounts are opted in but still need the global switch. Checks consume upstream quota and are logged with the internal sourceintelligence_check.Responses keeps native request semantics, and Responses WebSocket connections run independent streams in parallel (#788, @dundunge). The Responses relay now keeps
reasoning.effort,text.format, JSON Schema constraints and large integers as sent, and native fields take precedence over compatibility aliases such asreasoning_effortandresponse_format. An opt-in strict mode, enabled per request withX-Codex2API-Strict-Compatibility: trueor globally withCODEX_STRICT_RESPONSES_COMPAT=true, rejects fields and tool or output schemas that the native Codex path would drop or rewrite with400 unsupported_feature, listing them inerror.details.fields. It checks against the native Codex account actually selected, so relay accounts are not blocked, and usesresponse.failedonce SSE is committed and an error frame on WebSocket. OnGET /v1/responses,response.createframes keep FIFO order within the default stream and within eachstream_id, while different streams run in parallel: up to 16 active turns and 32 named streams per connection, with bounded queues. A request failure on one named stream no longer closes the other healthy streams. A connection can also continue from astore:falseresponse committed on another of its own streams, with the same API key, group, account and credential isolation as before. Probedexperimental_supported_toolsare stored and the Codex model manifest advertises the intersection across the accounts a key can reach.response.appendandresponse.steerreturnunsupported_feature. Seedocs/RESPONSES_COMPATIBILITY.md.Antigravity publishes Gemini 4 Argon in three thinking tiers. Once an account's catalog contains the
gemini-4-argon-highbacking, the gateway publishesgemini-4-argon-low,-mediumand-high, mapped to namedthinkingLevelvalues; the baregemini-4-argonalias defaults to high./v1/messagesnow folds bare Antigravity logical model names into their fixed tier before key limits and account selection, while relay accounts keep the logical name. The Codex model manifest shows Argon as a single choice with per-key reasoning levels and a 1,048,576-token context window. Disabled catalog placeholders such asgemini-4-argon-disabledstay visible in the admin catalog with a disabled overlay, but they are never advertised, scheduled or picked for connection tests, and a batch test that only finds disabled models no longer marks the account as errored. Catalog models without quota metadata show an unknown quota instead of an invented remaining percentage. Argon generation has not been verified against a live Ultra account.Antigravity Workspace and enterprise accounts can use their own Google Cloud project. Google only provisions a managed Cloud Code project for consumer tiers, so Workspace accounts on Gemini Code Assist Standard or Enterprise finished onboarding without a project and could not be dispatched. The Antigravity edit dialog gains a GCP project ID field (
user_project_id, stored asantigravity_user_project_id). The project is sent toloadCodeAssistand, for non-free tiers,onboardUser, and saving it resyncs the account immediately. Projects returned by Google still take precedence, and the free tier never receives the user project because naming one there fails withFAILED_PRECONDITION. When onboarding ends without a project, the error now says whether the tier requires a caller-owned project and how to set it.The unsupported-model cooldown is configurable, and an exhausted pool reports the real error. The new setting
oauth_unsupported_model_cooldown_seconds(default 1800, range 0–1800, 0 disables) controls how long an account stops serving a model after upstream answers "model is not supported when using Codex with a ChatGPT account". Other models and the account's health are unaffected: the 400 no longer counts as an account failure. Lowering or disabling the cooldown clears existing ones longer than the new value. Responses, Chat Completions and Messages clients no longer get a 503 "no available accounts" for this case: when the last attempt failed with the 400, the upstream error is passed through, and when every eligible account is cooling down for it, the 400 (codemodel_not_supported) names the model and the earliest recovery time.Fixes
gpt-6.1-sol no longer fails on every plan with "not supported when using Codex with a ChatGPT account" (#793, reported by @syunnrai123). Upstream returns the same 400 when the plan lacks a model and when the outbound client version is below the model's real minimum. gpt-6.1-sol declares
minimal_client_version0.153.0 but only appears in the models manifest from 0.159.0, so the bundled 0.153.3 was rejected everywhere and the gateway cooled each account down as if its plan were the problem. The bundled Codex CLI version and thecodex_min_cli_versiondefault for new installations move to 0.160.0, and official 0.160.0 Desktop and VSCode pairs are added so those User-Agent kinds clear the gate without a sync. When a Pro-tier account (Spark excluded) reports the error, it is treated as a version gate: no cooldown is written, and lower-tier failures with the same model and outbound version are not cooled down either for 30 minutes. A client-version sync that stores a newer version clears existingmodel_not_supportedcooldowns, including through the legacy CLI-only sync endpoint. The outbound version is logged on these failures, and gpt-6.1-sol is marked as unavailable for API-key auth like the rest of GPT-6.Credit override now actually serves traffic while quota auto-pause is configured (#791, reported by @xiaobulv). The account dialog showed credit override as active while the account received no requests. Auto-pause thresholds cap at 100%, so any account, group or global 5h or 7d auto-pause stopped dispatch before the window could run out and switch to credits, and the list still showed the "using credits" badge. While credits are covering, auto-pause and the 5h guard band (concurrency clamp and dispatch penalty) now step aside; they apply again once credits run out or a workspace hard stop lands. Turning credits on also releases a premium 5h penalty (
rate_limited_5h) recorded from response headers or WHAM, not only the 7d one. Real/responses429s are recorded under a separate reason and still apply.Antigravity Gemini tool loops no longer fail with "Function call is missing a thought_signature" (#792, reported by @Likhixang). Replayed function calls only got the skip-validator signature stub when the upstream model name contained flash, pro or thinking, or was exactly
gemini-4-argon-high. A pass-through Gemini model such as baregemini-4-argonsent unsignedfunctionCallparts, so every multi-turn tool loop failed. Everygemini-backing now gets the stub, on the Responses, Chat Completions and Messages conversion and in native/v1betasanitization. Claude and GPT-OSS backings are unchanged.Claude Code's built-in WebSearch works through
/v1/messages(#784, @Dominic485649). The Anthropic-to-Responses conversion treated Anthropic server tools (web_search_20250305,web_search_20260209,web_search_20260318, preview variants and name-onlyweb_search) as ordinary functions, which failed upstream with 40011129or returned an emptyweb_searchtool call that no client would run. They now become a hostedweb_searchtool, keepinguser_locationand domain filters, while a customweb_searchfunction with aninput_schemastays a function. Upstreamweb_search_callitems come back asserver_tool_useandweb_search_tool_resultblocks in streaming and non-streaming responses, including the query delta, andstop_reasonstaysend_turnafter a hosted search. Failed or incomplete searches return a pairedweb_search_tool_result_errorinstead of a danglingserver_tool_use. A forcedweb_searchchoice usesallowed_toolswithmode: required, so the model cannot pick another function instead, and function tools withoutinput_schemaget empty parameters.The first-run setup requires a one-time token from the service log. The bootstrap endpoint authorized any request that appeared to come from a private address. Behind Docker Desktop, rootless port forwarding or a private-network reverse proxy, public requests already arrive from a private peer, and
X-Forwarded-Foris client-controlled, so withADMIN_SECRETunset anyone who could reach the port could set the admin secret first. The service now generates a token in memory, prints it in the startup banner and log, requires it onPOST /api/admin/bootstrap, and revokes it after a successful setup;bootstrap-statusissues a new one if the secret is cleared at runtime.BOOTSTRAP_ALLOWED_CIDRis now matched against the direct TCP peer, so forwarding headers cannot spoof their way into it. Only wrong-token attempts count against the rate limit, the audit log records the real peer and any claimed forwarded IP, and the setup page has a token field with the log lookup command.Large Codex histories allocate far less memory before dispatch (#787, reported by @HanYC666). A 10 MiB Responses body allocated about 232 MB per request before reaching upstream, which on a Pi Zero W meant 20–90 s of full CPU and RSS peaks near 300 MB. Field cleanup on the HTTP, compact and WebSocket paths now deletes only fields that are present and skips writes that would not change the bytes, the image-generation check reads top-level fields in one pass, several input scans read the array without copying it, and the request size limiter reads a declared
Content-Lengthinto one buffer. Output bytes are unchanged. Per 10 MiB request, allocation drops from 232 MB to 87 MB; per 1 MiB request, from 23.7 MB to 11.3 MB.One busy API key no longer stalls the durable image job queue. Workers took the oldest queued job and then waited for its API key's concurrency slot, so a key saturated by its own requests, such as long streams, held workers while other keys' jobs waited. Workers now look at the oldest queued job of each key and claim only jobs whose key has a free slot. Two new limits apply when the queue is enabled with
IMAGE_JOB_WORKERS:IMAGE_JOB_MAX_QUEUED_PER_KEY(default 1000, 0 is unlimited) makes job creation return 429 withRetry-Afteronce a key has that many queued jobs, andIMAGE_JOB_MAX_QUEUE_WAIT(default24h, 0 disables, minimum1m) fails jobs that have not started within that time and removes their stored reference images. Those jobs never reached upstream and can be retried. A(status, api_key_id, id)index is added.Native Codex HTTP continuations no longer silently drop history (#788, @dundunge). A
previous_response_idthat the gateway cannot resolve from the requesting owner's cache now returns 409 (503 when the cache backend fails), instead of answering a turn without its history. New tool-call outputs are appended to the parent snapshot, and duplicates are skipped only when the full parent prefix and overlappingcall_ids match; partial or conflicting replays return409 response_context_unavailable. Duplicate top-levelinputorprevious_response_idkeys, including escaped duplicates, return 400 so different JSON parsers cannot pick different values. HTTP, compact and upstream WebSocket requests drop top-level gateway envelope fields such astypeandstream_idwhile keeping nested fields of the same name. The built-intool_searchtool no longer gets an injecteddescription, andbackground: falseis no longer mistaken for the image background extension. First-run setup now fills the idle chat and blank WebSocket retention settings with their default of 8, and an explicit 0 is kept.The public key-usage page rejects disabled API keys. It predated the per-key enable switch, so a disabled key could still read its usage summary, limits and recent request logs, and was shown as active. Disabled keys now get 401 and the attempt is audited, matching the proxy and the Image Studio portal. Expired and quota-exhausted keys stay readable so their holders can see why calls fail.
The pricing poller no longer times out at startup on slow SQLite storage (#778, reported by @HanYC666). The first read of the official pricing sync config ran table setup, including an insert that needs the SQLite write lock. After an upgrade the usage rollup backfill holds that lock almost continuously on slow storage, so the 5-second startup read failed with "context deadline exceeded". The config is now read first, and setup runs only when the read fails.
v3.1.0Compare Source
Fixes
Antigravity Claude models can call tools again (#783, reported by @ATM-M). Every Claude request that carried tools failed with 400
tools.0.custom.input_schema.type: Input should be 'object'. This happened on/v1/chat/completions,/v1/messages,/v1/responsesand native/v1beta; text-only requests and Gemini worked. Tool schemas travel asparametersJsonSchema, which Cloud Code hands to Claude verbatim as Anthropicinput_schema, and since v2.9.4 the schema cleaner had uppercased every type (OBJECT,STRING). Types are now lowercase at every level, and Gemini accepts both casings. Claude also refuses a forced tool choice (Anthropictool/any, Chatrequiredor a named function). The Claude 5.5 family always refuses it, and Claude 4.x refuses it while thinking is enabled. In those cases the gateway sendsAUTOinstead and drops the allowed function names. Claude 4.x without thinking keeps the forced choice, and Gemini is unchanged./v1/messageskeeps Claude model IDs that Antigravity serves instead of mapping them to Codex. The built-in Anthropic-to-Codex default map (for exampleclaude-sonnet-4-6→gpt-5.5) ran before the gateway checked whether an account could serve the requested ID under its own name. An Antigravity-only key got 503 "No available accounts", and a key that could also reach Codex silently got a GPT answer. The default map is now skipped when an account visible to the key publishes the ID directly, such as an Antigravity public model or a model declared by a relay account. Only structural conditions count: the key's visibility (the same as for/v1/models), its upstream channel and its affinity groups. Cooldowns and rate limits don't, so a busy pool never swaps in another vendor's model. Explicit model mappings still take precedence, and keys without such accounts keep the Codex fallback.Structured output on Antigravity Claude returns the JSON instead of a 500. When a Claude model gets a
json_schemaresponse format, Cloud Code forces an internaljson_modetool. The non-streaming answer comes back as ajson_modefunction call with finish reasonOTHER, which the gateway reported asantigravity response terminated with OTHER. That call is now turned into the JSON text answer, with key order preserved, preamble text dropped and thoughts kept. This applies to the Responses, Chat Completions and native/v1betapaths, streaming and non-streaming.OTHERbecomes a normal stop once the answer has made a tool call, and requests that declare their ownjson_modetool are left alone. Claude 5.5 rejects the forced tool upstream, so those requests now fail with a 400antigravity_feature_unsupportederror namingjson_schemastructured output, instead of an opaquetool_choiceerror.v3.0.9Compare Source
Features
The Antigravity account page gains batch delete and a full set of batch operations (#782, reported by @10373064). Selected accounts can be synced, tested, regrouped, enabled or disabled, locked or unlocked, reset, exported or deleted into the recycle bin, and API-key accounts can have their model list replaced in bulk. Sync and test can also target the current filter, and a one-click clean moves abnormal (banned or errored) accounts to the recycle bin using the same definition as the list. The quota column shows each quota group's 5h and weekly buckets with reset countdowns and marks snapshots older than six hours. Stat cards, status and credential-type filters, sorting by quota usage, today's requests or total requests, today and request columns, and health bars match the other channels. Clicking a row opens the shared account sheet with previous/next navigation and model cooldown management; clicking the quota opens a wide quota and access window with quota groups, Code Assist access and tiers, state and capabilities, AI credits and per-model quota. The single-row "refresh quota" and "refresh credential" buttons, which ran the same sync, become one sync action. Adding one account and importing files are separate entries: the add dialog detects whether the pasted credential is JSON, a refresh token or malformed JSON, the import dialog accepts dragged JSON files or many pasted refresh tokens, and proxy and group settings sit in a collapsible section.
Account refresh endpoints sync Antigravity accounts, and the account list filters and sorts them (#782).
POST /api/admin/accounts/:id/refreshandPOST /api/admin/accounts/batch-refresh, including SSE progress, filter selectors and bounded concurrency, now run the full Antigravity control-plane sync (credential, project, access and quota). Disabled accounts are recognized from the database because they are not in the runtime pool. The paged account list acceptsauth_kind=oauth|api_keyfor Antigravity, its summary counts OAuth and API-key accounts, andsort=usageorders accounts by the used share of their tightest quota bucket, the same key the scheduler uses. The dashboard's Antigravity quota distribution reads the same value.Antigravity exports are one JSON file (#782).
GET /api/admin/accounts/antigravity/exportnow defaults toformat=json: one account downloads as a single credential document and several as one JSON array, like the Codex and Claude exports. The importer reads both shapes, and the import dialog automatically splits files with more than 500 accounts into batches and merges the results.format=zipkeeps the previous one-file-per-account archive.Fixes
Long-range usage statistics no longer time out on slow SQLite storage (#778, reported by @HanYC666). The new
usage_log_hourlytable aggregates usage logs per UTC hour by API key, channel, model, endpoints, status, stream and internal flag. It is updated in the same transaction as each log batch, cleared with the logs and backfilled in the background; queries keep reading detail rows until the backfill completes. Queries read whole hours from the rollup and edge hours and window boundaries from detail rows, so results are unchanged. Rows written outside the normal path are detected and repaired, and the last three closed hours are re-counted every 20 minutes. This covers the public key-usage report, admin range totals and breakdowns, the error summary and request log counts; filters on account, search text, error kind or request shape other than stream still scan detail rows. On a 400k-row SQLite benchmark with a 30-day range the key-usage report drops from 950 ms to 12 ms and admin stats from 2.1 s to 21 ms. API-key rankings now break label ties by key ID.Usage stat cards no longer show the previous range's numbers when a refresh fails (#778, reported by @HanYC666). A failed silent refresh after changing the range or filters kept the old figures under the new range's label, so a custom range spanning all history could show roughly today's totals. Cards are dimmed while new filters load, and a failed refresh covers them with the error and a retry button.
Edit buttons in the account group manager show a label. The
common.edittranslation was missing, so its tooltip showed the raw key.Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Never, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.