Add an xAI OAuth manager using the OAuth 2.0 Device Authorization Grant
with endpoints resolved from xAI's OIDC discovery document. All HTTP goes
through the app-managed proxy client.
- Managed provider kind xai_oauth: forced openai_responses wire format,
pinned api.x.ai base URL, bearer injection gated to the xAI origin,
tokens registered for log redaction, single-auth-key takeover policy.
- Token cache cannot bypass account state: cache hits re-validate account
usability, refresh commits run under the mutation lock with a
refresh-token CAS check, and pending logins are re-checked before an
account is persisted.
- Refresh classification: 401/403 with any body and 400 with a non-JSON
body mark the account for re-auth; 429/5xx stay transient.
- Shared auth_* commands dispatch to xAI with guard types mirroring the
Copilot/Codex branches.
Codex >= 0.144.5 requires supports_reasoning_summaries in every external
model catalog entry and rejects the whole file at startup when it is
missing, which bricks both the CLI and the desktop app.
The ProxyChat catalog template is cloned from dynamic sources first
(models_cache.json, then `codex debug models --bundled`). models_cache.json
is shared by every Codex install on the machine and each version serializes
its own ModelInfo shape, so the cache's field set follows whichever process
wrote it last and cannot be assumed to satisfy the current external-catalog
schema. Deleting the generated catalog never helped: any provider save or
switch regenerated it from the same stale template.
Backfill parser-required fields (explicit whitelist, currently only
supports_reasoning_summaries) from the bundled static template when the
dynamic template lacks them. Optional capability fields are deliberately
NOT backfilled so their missing-means-parser-default semantics survive,
and existing values always win.
The Kimi For Coding subscription reports its K3 model under the short
id `k3` (no `kimi-` prefix), whereas the regular Moonshot API still uses
the full `kimi-k3`. Seed a `k3` alias row right after `kimi-k3` at the
same official list price ($3/M in, $15/M out, $0.30/M cache read) so
coding-plan usage is priced correctly. Mirrors the existing
hunyuan-hy3/hy3 bare-alias precedent.
Pricing is matched by exact model id, so this does not touch the
`kimi-for-coding` endpoint alias (intentionally unpriced, subscription
semantics) nor risk prefix mismatches. Seed-only, no schema bump.
Document API key and ChatGPT OAuth routing flows for using Codex models in Claude Code, including configuration screenshots and troubleshooting guidance.
Prefix anchored npm invocations with their sibling bin directory so env-based Node shebangs work under a minimal GUI PATH. Cover Codex repair commands and add a regression test.
The cost field on OpenClaw preset models is denominated in USD per
million tokens (as the Claude entries already were), but 15 entries
carried $/1K-style decimals or stale values. Reprice everything at the
model's official list price, mirroring the built-in pricing table, so
usage is always valued at standard rates regardless of channel:
- glm-5.1 (Zhipu CN/EN, ModelScope): 1.4/4.4, cache read 0.26
- qwen3.5-plus: 0.26/1.56, cache read 0.052
- kimi-k2.7-code and the kimi-for-coding alias (K2.7 Code per official
docs): 0.95/4, cache read 0.19
- MiniMax-M2.7 (official + SiliconFlow): 0.3/1.2, cache read 0.06,
cache write 0.375
- KAT-Coder-Pro: 0.3/1.2, cache read 0.06
- LongCat-2.0: 0.75/2.95, cache read 0.015
- Ling-2.5-1T: 0.56/2.24 (official CNY 4/16 at ~7.14)
- deepseek-v4-pro: 0.435/0.87 (old 1.68/3.36 was CNY 12/24 left
unconverted), cache read 0.003625
- kimi-k2.5 (Nvidia NIM): 0.6/3, cache read 0.1
Subscription-plan endpoints and free-tier hosts intentionally show
list prices too, so plan users can see the standard value of their
usage.
Add kimi-k3 (1M context, 131K max output) to the Kimi provider preset
model lists for Codex, Hermes, OpenClaw, and OpenCode, appended after
kimi-k2.7-code so the catalog-first-row default backfill is unchanged.
The Kimi For Coding plan presets keep the kimi-for-coding endpoint
alias and are intentionally untouched.
Seed kimi-k3 at the official list price ($3/M input, $15/M output,
$0.30/M cache read; released 2026-07-16 with a 1M context window).
Cross-checked against the Moonshot pricing docs, OpenRouter, and
models.dev. Seed-only change: ensure_model_pricing_seeded picks it up
on next launch, no schema version bump needed.
Frontend half of the logging overhaul.
Capture:
- Add a global error boundary plus window error/unhandledrejection
handlers that persist renderer errors via tauri-plugin-log (new
@tauri-apps/plugin-log dependency + log:default capability), so a
white-screen crash leaves a trace.
Redaction (two layers over every logged value):
- Structured serializer: redact by sensitive property name (arrays and
nested values included) and by opaque value shape.
- Text layer, the universal final pass: redact URL credentials/query,
auth schemes, known secret shapes, and named-key array/object values.
The container rule closes prefix+JSON, double-encoded, and POJO-error
bypasses regardless of which entrypoint the structured data came from.
- Render Errors as redacted message + native stack across V8 and WebKit
(macOS/Linux) without depending on a single stack format.
- Bound all inputs and drop oversized JSON to keep the UI responsive.
i18n:
- zh / en / ja / zh-TW for the new log settings and error text.
Backend half of the logging overhaul.
Retention:
- Keep the last 4 rotated files at 20MB each and stop deleting logs on
startup, so a crash's prior-run logs survive a restart.
- Apply the persisted log level right after plugin registration instead
of at the end of setup.
- Bound crash.log with size-based rotation (5MB x 2).
Secret redaction on every log path:
- Proxy: strip userinfo/query from upstream URLs (keep path for
diagnostics), exact-match redact known auth.api_key/access_token,
classify request/response bodies instead of logging them, header
allowlist.
- Redact the Gemini `?key=` in cache-trace endpoints.
- Omit MCP custom-field values (headers may carry tokens).
- Redact deeplink and model-fetch URLs before logging.
Docs:
- FAQ points users to the persistent crash.log for support workflows.
The legacy sudocode.us provider was replaced in place by the sudocode.chat
sponsor (618723b4) because the two unrelated companies share the SudoCode
name. Bring the legacy provider back and distinguish the two by their
domain suffix.
- Rename the sponsor preset to "SudoCode.chat" across its six clients;
partner status, promotion copy (key "sudocode"), and icon unchanged
- Re-add "SudoCode.us" across all seven clients (including the previously
removed Gemini entry) with its pre-replacement config: gpt-5.5,
sudocode.us endpoints, sudocode.run fallback candidates
- Mark SudoCode.us as partner (isPartner) without a partnerPromotionKey:
promo copy is pending, and the promo box only renders when a key exists
- Give the SudoCode.us Hermes entry a distinct slug (sudocode_us) so both
providers can coexist in the additive ~/.hermes/config.yaml
- Restore the legacy logo from git history as sudocode-us.png and register
it in the hand-maintained icon index and metadata
Switching providers or toggling proxy takeover on Windows flashed a
transient cmd window and froze the UI for up to a couple of seconds.
Three fixes:
- Spawn `codex debug models --bundled` with CREATE_NO_WINDOW so the
console child of the GUI-subsystem app (npm's codex.cmd runs via
cmd.exe) no longer opens a visible window.
- Cache the ProxyChat model catalog template in a process-wide OnceCell:
only successful loads are cached, failures stay retryable, so the
Codex CLI starts at most once per app run instead of on every switch.
- Run switch_provider via spawn_blocking: sync Tauri commands execute on
the main thread, so the blocking catalog generation (and the
block_on'd per-app switch lock) froze the UI. Concurrency is already
serialized by ProxyService::lock_switch_for_app.
Normalize function tool parameters on the Codex Responses -> Chat Completions bridge: default null/missing parameters (direct and nested function forms) to {"type":"object","properties":{}}, coerce explicit type:null, and add a root type for top-level oneOf schemas so strict OpenAI-compatible upstreams (DeepSeek etc.) no longer reject built-in Codex tools like codex_app__automation_update. Also hardens the Codex -> Anthropic tool path with the same object-type guarantee and adds regression coverage for all reported shapes.
The tray menu used a hardcoded zh (Simplified Chinese) fallback whenever
settings.language was unset (i.e. first install). On systems whose UI language
resolves to Traditional Chinese / Japanese / English via the frontend's
navigator-based detection, the tray therefore showed Simplified Chinese until
the user manually switched language once.
Detect the OS locale via the sys-locale crate and map it to a supported tray
language, mirroring the frontend getInitialLanguage precedence
(zh-TW/HK/MO/Hant -> zh-TW, other zh -> zh, ja -> ja, en -> en, otherwise zh).
This keeps the tray consistent with the UI from the first launch with no timing
window. An explicitly stored settings.language still takes precedence, so user
choices are never overridden. Adds unit tests for the locale mapping.
Co-authored-by: LaiYueTing <LaiYueTing@users.noreply.github.com>
Co-authored-by: Jason <farion1231@gmail.com>
* fix(ci): run backend checks on Windows/macOS and repair platform-gated tests
The backend CI job ran only on ubuntu-22.04, so every #[cfg(target_os =
"windows")] / macOS path — tests and clippy lints alike — was never
compiled or run. As a result main shipped 8 failing Windows unit tests and
a hard `cargo clippy -- -D warnings` failure on Windows, all invisible to
CI because it only builds and tests Linux.
Changes:
- ci: run the backend job on a {ubuntu-22.04, windows-latest, macos-latest}
matrix (fail-fast: false); gate the apt install step on runner.os ==
'Linux' and use `shell: bash` for the dist placeholder so it works on all
three runners.
- misc.rs: fix 6 stale `anchored_upgrade_windows` tests. Commit 5092fe51
removed codex from `prefers_official_update`, so codex now anchors to the
package manager with no `codex update ||` prefix; update the five
package-manager expectations accordingly, and retarget the no-sibling
"official-update-without-fallback" test to `claude` (still in the list) so
that branch stays covered instead of being silently dropped.
- codex_state_db.rs / codex_history_migration.rs: the two sqlite_home tests
built TOML basic strings from Windows paths, whose backslashes are invalid
escape sequences and made the override fail to parse; switch to TOML
literal (single-quoted) strings so the path is taken verbatim.
- clippy (13 Windows-only warnings): move `use std::io::Write` into the
#[cfg(unix)] block that actually uses it; convert 3 unneeded `return`s in
Windows-gated tail positions to expressions; mark 9 POSIX-shell helpers
#[cfg_attr(windows, allow(dead_code))] since they are used only by the
macOS/Linux terminal launchers.
Verified locally (Windows 11, Rust 1.95.0):
cargo test --lib → 1748 passed; 0 failed (was 1740/8)
cargo clippy -- -D warnings → clean (was 13 errors)
cargo fmt --check → clean
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(skills): resolve home via get_home_dir so tests isolate on Windows
services/skill.rs called dirs::home_dir() directly in five places. On
Windows dirs::home_dir() resolves through the Known Folder API and
ignores HOME/USERPROFILE, so the CC_SWITCH_TEST_HOME override set by the
test harness never applied: the skill_sync integration tests scanned the
runner's real user profile, found no skills, and failed (the first panic
then poisoned the shared test mutex, cascading to all seven). On Unix
the harness also sets HOME, which dirs::home_dir() honors, so the suite
passed there by accident.
Route all five call sites through crate::config::get_home_dir(), the
crate-wide home resolver that prefers CC_SWITCH_TEST_HOME. The three
now-unreachable GET_HOME_DIR_FAILED error branches are dropped:
get_home_dir() is infallible, matching every other config-dir resolver.
Production behavior is unchanged (CC_SWITCH_TEST_HOME is unset outside
tests, so get_home_dir falls through to dirs::home_dir).
Add a regression test that discriminates on every platform by pointing
CC_SWITCH_TEST_HOME at a temp dir different from $HOME; it is marked
#[serial_test::serial] to stay mutually exclusive with the other tests
mutating the same process-global variable. Verified the test fails
against the old code on macOS with the same failure mode as Windows CI.
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Jason <farion1231@gmail.com>
Keep non-empty call IDs across continuation deltas and release parallel tool calls in Chat index order when identity fields arrive late. Preserve valid sparse and later calls during finalization.
* fix: normalize function parameters type to "object" for strict OpenAI-compatible providers
Some Responses tools carry parameters with `type: null` (e.g.
codex_app__automation_update), causing HTTP 400 from strict
OpenAI-compatible providers like DeepSeek that require
`{"type": "object", "properties": {...}}`.
This adds normalize_function_parameters() to ensure the type
field is always "object" in both branches of
responses_function_tool_to_chat_tool.
Closes#4705
* style: fix cargo fmt issues
* fix: handle null function parameters
Step-by-step guide for the v3.17.0 native Anthropic Messages upstream:
add a custom Codex provider pointed at a Claude-family /v1/messages
gateway, pick the anthropic upstream format, enable local routing, and
verify the chain. Covers the auth-field choice (Bearer vs x-api-key),
the Claude Code impersonation toggle, the 8192 max-output fallback, and
a FAQ entry for gateways that restrict keys to Claude Code only.
Includes four UI screenshots captured from the real 3.17.0 app with
sample data, and links the guide from the v3.17.0 release notes in all
three languages.
The routing-required toast for Anthropic-format Codex providers only had
a Chinese defaultValue in code; non-Chinese locales showed a mixed-language
message. Add the reason string to zh/en/ja/zh-TW following the phrasing of
the sibling proxyReason* keys.
The forced 1-hour cache_control TTL (schema v14) was a mistake. Injected
breakpoints return to Anthropic's standard 5-minute TTL, caller-owned
markers are preserved verbatim instead of having their TTLs rewritten,
and the 5m/1h cache-write buckets are removed from usage parsing and
pricing (back to the single aggregate cache-creation rate). The cache
TTL selector is removed from the rectifier settings panel along with its
i18n keys in all four locales.
SCHEMA_VERSION returns to 13: the unreleased cache_creation_1h_tokens
column and the v13->v14 migration are removed. The feature never shipped
in a release and the introducing commit was never pushed, so no
databases were stamped v14 outside this machine (local DB verified at
user_version 13).
Mapped GPT models were rejected by Codex clients with "model does not
support image inputs". Two root causes:
- Catalog entries for native-Responses/Anthropic providers cloned a
template whose input_modalities defaulted to ["text"], so every mapped
model was advertised text-only. model_catalog_json replaces Codex's
built-in model table wholesale, and both the TUI and the IDE extension
block images pre-send when the current model is found without "image".
- Editing the current Codex provider during proxy takeover only refreshed
the DB backup, so removing the mapping left a stale model_catalog_json
pointer (and its text-only catalog file) active in live config.
Changes:
- New shared model_capabilities module: explicit row declaration first,
then a confirmed text-only registry (exact tail match only — prefix
matching removed, variants enumerated so future -vl/-vision models fail
open), everything else unknown.
- Catalog generation writes input_modalities from that inference for all
tool profiles: unknown models fail open to ["text","image"]; only
confirmed text-only models are advertised as ["text"], giving users a
clear client-side prompt instead of silent image stripping.
- Live catalog reverse-import collapses modalities that match current
inference, so registry corrections are not frozen into hidden row
overrides and the rectifier's heuristic opt-out keeps working.
- Saving the current Codex provider while takeover owns live now
re-projects the live config (mirrors the hot-switch path), so mapping
edits and removals take effect immediately.
- Media rectifier delegates to the shared module; its preflight toggle is
documented (4 locales) as proxy-request-only, never affecting catalog
capability declarations.
Replace the legacy sudocode.us provider (a name collision) with the new
paid sponsor SudoCode on sudocode.chat, updated in place across six
clients: Claude Code, Codex, Claude Desktop, OpenCode, OpenClaw, Hermes.
- Switch endpoints to api.sudocode.chat, add isPartner +
partnerPromotionKey, and add four-locale partnerPromotion copy
- Claude Code / Desktop use direct passthrough (no model mapping)
- Codex / OpenCode / OpenClaw / Hermes use gpt-5.6-sol
- Remove the Gemini entry (outside sponsor scope)
- Replace the provider icon with the new brand PNG
ChatGPT's Codex backend routes model availability by the originator and version header pair. Requests identifying as cc-switch without a version were assigned to a cohort where gpt-5.6-luna resolved to an unavailable internal engine, resulting in a misleading 404 Model not found response.
Identify takeover requests as codex_cli_rs and send version 0.144.1, satisfying luna's minimal_client_version requirement of 0.144.0. A direct HTTP A/B test confirmed the existing headers returned 404 while the aligned identity completed successfully, so no WebSocket transport workaround is required.
Drop the Max Context Tokens / Auto Compact Window template inputs from
the Codex and Kimi For Coding presets and hardcode the values in the
preset env (372000 / 262144). The rare user who wants different numbers
can edit them directly in the JSON editor.
Both keys stay on purpose: the compact window resolves as
min(model window, value), so matching the window is behavior-neutral
today, but the explicit env pins compaction locally against
remote-config experiments dialing it down.
Claude Code caps unknown model ids at 200K, so the preset's standalone
CLAUDE_CODE_AUTO_COMPACT_WINDOW=262144 was clamped by min(window, value)
and never took effect. Pair it with CLAUDE_CODE_MAX_CONTEXT_TOKENS and
route the endpoint's kimi-for-coding alias on every tier, since both
context envs are ignored for claude-* prefixed model ids.
Saved providers get the same context defaults injected into effective
live settings at switch time, with a mirror-inverse strip on backfill so
injected values never harden into provider config. Explicit user values
always win over the injected defaults.
- Add the bare gpt-5.6 row (official Sol alias) plus effort-suffix variants
mirroring the gpt-5.5 accounting shape, priced at Sol rates
- The GPT-5.6 family charges cache writes at 1.25x the uncached input rate
(new for OpenAI; earlier GPT models keep their correct zero): set
6.25 / 3.125 / 1.25 for Sol / Terra / Luna across seed rows
- Repair earlier zero-value gpt-5.6 tier seeds in existing databases,
matching only untouched rows so user-customized prices survive
- Update Codex OAuth presets to the gpt-5.6 family (haiku -> gpt-5.6-luna)
and bump the custom Codex template default model
- Inject CLAUDE_CODE_MAX_CONTEXT_TOKENS / CLAUDE_CODE_AUTO_COMPACT_WINDOW
(372000, the ChatGPT Codex catalog window with a ~353K effective budget,
openai/codex#31860) into effective live settings so Claude Code stops
assuming a 200K window and compacts before the upstream rejects the prompt
- Gate the injected defaults on every configured model being gpt-5.6*:
gpt-5.5's upstream catalog oscillates between 272K and 372K and must not
inherit them; explicit user values always win
- Strip the injected values on switch-away backfill (mirror-inverse of the
injection conditions) so program defaults never harden into per-provider
explicit values, and keep both keys out of the shared common-config snippet
Let users switch between the built-in OpenAI provider and third-party Codex providers directly from the provider panel while takeover mode remains active.
Centralize the frontend capability predicate so only the fixed codex-official seed receives native-login routing support, and keep copied UUID-based official entries clearly marked as unsupported.
Add an idempotent backend command that recreates the deleted official seed, wire it into the add-provider flow, refresh localized guidance, and add mutation and provider-action regression coverage.
Do not derive unauthenticated health-check targets from runtime adapter defaults for official providers. Batch checks now skip official entries, and direct base-URL resolution fails explicitly instead of probing first-party endpoints without credentials.
Cover the Codex official provider in the stream-check regression tests so future adapter changes cannot silently reintroduce these probes.
Allow the built-in Codex official provider to participate in takeover mode while preserving Codex's native OAuth or API-key credentials instead of persisting them into provider records.
Project official routing into a dedicated TOML provider, normalize inline tables, clean stale managed placeholders, and fail closed when the live configuration cannot be transformed safely.
Validate forwarded authorization, make official 401/403 responses non-retryable, avoid circuit-breaker pollution, and share the first-party ChatGPT endpoint across the Codex and Claude adapters.
Parse and retain Anthropic's ephemeral 5-minute and 1-hour cache-creation token buckets while preserving the existing aggregate cache-write metric for compatibility.
Price 1-hour writes at the documented premium relative to the configured 5-minute write rate, clamp inconsistent provider details safely, and include TTL buckets in usage diagnostics.
Persist 1-hour cache-write tokens with schema version 14 so zero-cost backfills and later pricing updates retain the original TTL semantics. Keep session import paths compatible through zero-valued detail fields.
Honor both the optimizer master switch and the cache-injection sub-switch before mutating native optimizer requests.
Use the available four-breakpoint budget across tools, system content, the latest cacheable message, and an older user anchor for long tool-heavy conversations.
Preserve caller-owned breakpoint limits, avoid thinking blocks as cache targets, normalize configured TTLs, and add regression coverage for disabled optimization and long histories.
Fail closed on HTTP 2xx failure envelopes and pre-output SSE failures so semantic upstream errors can trigger failover instead of becoming empty successful replies.
Finalize incomplete and truncated streams explicitly, handle clean EOF and whole JSON responses, and keep tool-call stop reasons and terminal event ordering consistent.
Preserve structured tool results, URL images, documents, system roles, and signed thinking across both conversion directions. Drop incomplete historical tool calls safely and classify malformed completed arguments as non-retryable client requests.
Keep Codex-to-Anthropic prompt caching enabled by default while honoring the dedicated cache-injection switch.
Codex always sends prompt_cache_key in its Responses requests, but the
Responses -> Chat Completions conversion dropped it, breaking session
cache affinity on upstreams that route by key (e.g. Kimi Coding).
- Re-inject prompt_cache_key after conversion in the forwarder: an
explicit client key wins, otherwise a client-provided session ID;
generated per-request UUIDs are never sent upstream.
- Provider-aware gating: "auto" enables only known-compatible upstreams
(api.openai.com, api.kimi.com/coding) because strict gateways reject
unknown fields with HTTP 400 (e.g. Fireworks); an advanced
Auto/Enabled/Disabled override is available on the Codex form in all
four locales.
- Kimi For Coding preset opts in explicitly.
Warn when caller-provided cache breakpoints already exceed the supported total of four while preserving the original markers and upgrading their TTLs.
Clarify that automatic injection is governed by the remaining breakpoint budget, and add regression coverage proving excess caller markers are never deleted or reordered.
Round-trip encrypted Responses reasoning items through bridge-owned Anthropic thinking blocks, discard orphaned reasoning-only history, and consume the official reasoning text event vocabulary.
Track concurrent streaming items by stable IDs and output indexes, reuse a dedicated fallback block for keyless legacy reasoning, recover tool arguments from done events, and close blocks in protocol order.
Normalize empty or incomplete non-streaming tool arguments, reject malformed completed calls, and persist upstream usage before returning terminal conversion errors.
Parse cache_write_tokens from OpenAI usage details and preserve cache creation data across Chat, Responses, and Anthropic conversion paths.
Add explicit input-token semantics to request logs and rollups so legacy rows subtract cache reads only while new total-inclusive rows subtract both cache reads and writes. Migrate v12 databases, normalize rollups to fresh input, and cover historical backfill behavior with regression tests.
Add a show/hide toggle for the header project profile switcher under
the Homepage Display section in settings. Defaults to visible so
existing users keep the current behavior.
Expose the top-level `model` key of config.toml as an editable field in
the Codex provider form, so users can switch to newly released models
(e.g. gpt-5.6) without waiting for a preset update — preset updates only
affect newly added providers, existing ones keep their saved TOML.
The field syncs bidirectionally with the TOML editor (mirroring the
base-URL pattern), suggests models from the mapping catalog plus the
provider's /models endpoint, and offers a one-click "add to mapping"
action when the value is outside a non-empty catalog. Hidden for
official providers.
Details:
- Save-time catalog sync now only backfills the first mapping row into
the top-level model when the field was left empty, so the explicit
field wins over the implicit row-0 sync
- Escape model names (and base_url) with TOML basic-string escaping and
strip control characters from field input: /models ids are remote
data and unescaped interpolation could inject config.toml lines
(e.g. a forged [mcp_servers.*] command)
- The strict model-line matcher now recognizes escaped output, empty
strings and single-quoted literals, keeping extract/set round-trips
stable; deliberately no key-only loose matching (it would misfire on
assignment-looking text inside multiline strings)
- Invalidate the fetched model list whenever the request identity
changes (base URL, full-URL toggle, API key, custom UA) and discard
in-flight responses via a sequence guard, so the dropdown never shows
a previous provider's models
- i18n for zh/en/ja/zh-TW
Add Hunyuan Hy3 (released 2026-07-06, 256K context) to seed_model_pricing
under both the hunyuan-hy3 and hy3 ids, since the upstream billing id isn't
yet confirmed and one of the two should match logged usage.
Prices come from Tencent's launch-day list price (CNY 1 / 4 / 0.25 per 1M
input / output / cache-hit), converted at 1 USD ~= 7.14: 0.14 / 0.56 / 0.035.
cache_write is "0" (no published write rate). Hy3 actually uses input-length
tiered billing (<16K / 16-32K / >=32K); the single-price table holds the
lowest tier, so long-context requests are under-billed until this is revisited
against the official billing page. New model, so seed only.
Add the three GPT-5.6 tiers to seed_model_pricing, cross-checked against
OpenAI's official pricing page and OpenRouter:
gpt-5.6-sol 5 / 30 / 0.50 (cache read)
gpt-5.6-terra 2.50 / 15 / 0.25
gpt-5.6-luna 1 / 6 / 0.10
cache_write is "0": OpenAI publishes only a cached-input (read) rate and no
separate cache-write price, matching the gpt-5.x family convention. Base ids
only for now — effort-suffix variants are deferred until the upstream logging
suffix set for 5.6 is confirmed. New model, so seed only (no repair branch,
no SCHEMA_VERSION bump).
Switching the Claude provider from a third-party (DeepSeek/MiMo/...) to a
managed Codex provider wrote both ANTHROPIC_API_KEY and
ANTHROPIC_AUTH_TOKEN as PROXY_MANAGED into ~/.claude/settings.json,
making Claude Code warn "Both ANTHROPIC_AUTH_TOKEN and ANTHROPIC_API_KEY
set - auth may not work as expected" on every run.
The double key is an accretion artifact: the ManagedAccount takeover
policy originally injected only ANTHROPIC_API_KEY (Copilot, #1049), and
the Codex fix that preserved ANTHROPIC_AUTH_TOKEN to avoid the login
prompt (#3784 / PR #3789) added the token on top without removing the
API key insert.
Inject exactly one placeholder instead: AUTH_TOKEN for Codex-managed
providers (keeps the #3784 fix), API_KEY for Copilot (keeps the #1049
behavior). Local-proxy auth is unaffected - the forwarder resolves the
PROXY_MANAGED placeholder from either header.
Updates the three Codex takeover tests to assert API_KEY is absent and
adds a regression test for the exact third-party -> Codex switch from
the report.
Fixes#4919