Icons that paint with currentColor inherited the preset button's
text-muted-foreground, so the same icon looked mid-gray in the preset
selector but near-black in the form's icon preview and on the provider
card. The mismatch hit all 28 monochrome icons and was most visible on
9527CODE, whose 0.82-opacity base layer lightened the gray further.
Unselected preset icons now take text-foreground; selected ones still
inherit the button's text-white. The universal preset row gets the same
treatment. Brand-colored icons are unaffected because ProviderIcon sets
their color inline.
Baidu Qianfan and StepFun now ship native Responses presets for their
pay-as-you-go APIs, so the Chat-only examples name the offerings that
still route through Chat: Baidu Qianfan Coding Plan and StepFun Step
Plan. Synced across the zh/en/ja manuals.
- deepseek-v4-pro returns to its peak list price 1.32/3.96/0.044. The
2026-09-11 move to the V4.1 Flash price anticipated a cutover that
DeepSeek retracted on 2026-09-12. Replace that repair entry with one
that restores rows still at 0.3/1.2/0.006; keeping both would rewrite
the row back and forth on every start.
- Seed hy4-preview (CNY 6/18/0.3 at 7.14), qwen3.8-2.4t-a95b and
qwen3.8-27b (Alibaba Cloud international list prices).
- MiniMax CN: the remaining apps switch from api.minimaxi.com to
api.minimax.cn (Anthropic root /anthropic). Usage detection recognizes
both hosts and now matches on host labels (frontend, and the global
host in the backend), so look-alike hosts and URLs that only carry the
domain in their path are ignored. The quota query keeps
api.minimaxi.com, the only CN host documented for that endpoint.
- BaiLing: the remaining apps switch from api.tbox.cn to
api.ant-ling.com (/v1 and /anthropic) and default to Ling-2.6-1T,
since Ling-2.5-1T is no longer listed in the current docs. Ling-2.6-1T
is registered as text-only (vision ships as separate -VL models).
- Reword the DeepSeek V4 Pro note in the text-only registry: the vendor
keeps serving V4 Pro after September 14, 2026.
- Kimi For Coding: kimi-for-coding now serves K2.8 Preview (up to 1M,
text+image, low/high/max); the highspeed variant stays at 256K.
- DeepSeek: default to deepseek-flash (V4.1 Flash, text+image) and
declare deepseek-v4-pro text-only, matching the bundled official
catalog.
- Add native Responses presets for StepFun API (CN/intl,
step-3.7-flash), Baidu Qianfan pay-as-you-go (/v2) and iFlytek Astron
Coding Plan; subscription plans on the same hosts stay on Chat.
- Add hy4-preview to Tencent Hunyuan, and the open-weight
qwen3.8-2.4t-a95b / qwen3.8-27b to both pay-as-you-go Qwen platforms.
- MiniMax CN moves to api.minimax.cn and BaiLing to api.ant-ling.com.
- Disable Codex web_search on StepFun (function tools only), and
conservatively on Qianfan and Astron, whose Responses docs document no
hosted tools. The new hosts stay out of CODEX_NATIVE_RESPONSES_HOSTS
so Chat plans on the same hosts are never reclassified as native.
- Tencent Enterprise Token Plans stay on Chat: /plan/v3/responses is
listed, but TokenHub marks Kimi K2.7 Code unsupported and several
models as server-side Chat conversions, and the catalog levels were
verified on Chat only.
Follow-up to #7331 (Claude Desktop 3P configuration on Linux):
- Compile the Linux config-dir resolver and its three unit tests under
any unix test build so they run on macOS as well as CI ubuntu. The
gate is unix rather than test because the assertions use POSIX
absolute paths, which are not absolute on Windows.
- Open the provider -> Claude Desktop profile sync integration tests to
Linux: add the Linux profile path helper and pin XDG_CONFIG_HOME under
the temporary home (saved on construction, restored on drop).
- Update the support-scope table in the en/zh/ja user manuals to list
Linux and note that the Flatpak build always uses the host ~/.config.
A disabled React Query observer still returns the existing cache entry for
the same key, so a provider switched to the official subscription template
(or with its usage script disabled) kept showing the multi-plan chevron and
the expanded tiers left over from a previous script result.
Gate hasMultiplePlans with the same predicate that enables the usage query,
extracted as scriptUsageActive so the two cannot drift apart again.
Add a "Kimi Global" twin immediately after the domestic "Kimi" API preset and a "Kimi For Coding Global" twin after the domestic "Kimi For Coding" preset, in every preset file that ships them (claude, claude-desktop, codex, hermes, openclaw, opencode, pi).
"Kimi Global" points to the international open platform https://platform.kimi.ai?aff=cc-switch (apiKeyUrl mirrored as https://platform.kimi.ai/console/api-keys?aff=cc-switch) and swaps the endpoint host api.moonshot.cn for api.moonshot.ai with each file's path unchanged (/v1 or /anthropic).
"Kimi For Coding Global" points to the international site https://www.kimi.ai/code/?aff=cc-switch and swaps the endpoint host api.kimi.com for api.kimi.ai with the path unchanged (e.g. https://api.kimi.ai/coding/v1).
Domestic presets are unchanged; category, icons, apiFormat, model catalogs, endpointCandidates (host swapped), partnerPromotionKey and settings otherwise mirror the domestic blocks exactly.
primePartner stays only on the domestic presets so the new variants do not alter prime-partner ordering.
The Pi twins get distinct providerKey values ("cc-switch-kimi-global", "cc-switch-kimi-for-coding-global") because providerKey is the preset-level primary key and must not collide with the domestic presets.
Kimi Code plan purchases have resumed, so the README sponsor sections go back to leading with the coding plan instead of the API-only flow written during the purchase pause.
All four locales (EN/ZH/JA/DE) now present Kimi Code plan (中文站 | Global) as the primary CTA and the Kimi Open Platform API (中文站 | Global, with the first-top-up bonus) as the secondary one, mirroring the domestic|global split already used for API links.
The aff and track_id values are unchanged.
Reload the enabled prompt from its live file when the Prompts list loads, and refresh the open panel when the window regains focus, so external edits to CLAUDE.md / AGENTS.md show up without a restart.
- Keep saved templates available when the live file cannot be read.
- Skip the backfill for empty or whitespace-only files, matching enable_prompt.
- Skip the backfill while a sync/restore holds the sync lock, so a list load cannot write a stale live file into a freshly restored database.
Installing hugohe3/ppt-master from skills.sh failed with
ARCHIVE_TOO_MANY_ENTRIES: the GitHub archive we download is the whole
repository (13,248 entries), and the 10,000-entry cap added in #5811
treated it as a zip bomb.
- Raise MAX_ARCHIVE_ENTRIES to 30,000 for both the remote archive and
local ZIP paths, and align WebDAV's MAX_EXTRACT_ENTRIES so a skills.zip
containing such a skill still restores.
- Charge every file entry at least one 4 KiB block against the existing
512 MiB budget, mirroring directory accounting, so empty-file archives
are bounded by the byte budget rather than by the entry count alone.
- Add tests for a 13k-entry repo archive and for the per-file minimum
charge.
Fixes: https://github.com/farion1231/cc-switch/issues/7475
Add MiniMax Code (mcode) as a managed application: provider and model management through the native custom_provider configuration, MCP servers, Skills, global instructions (AGENTS.md), read-only local session history with resume, and usage import from the native runtime database. Native files shared by the TUI and desktop are written under the native lock with rollback when the database commit fails, unrelated native configuration is preserved, and the data directory honors MINIMAX_DATA_DIR and MAVIS_DATA_DIR. Deleting sessions stays in the native application because they are coupled to runtime state.
After deleting a managed ChatGPT account and logging in again, a Codex provider can still reference the old local account ID, which made route switching, takeover, startup restoration and rebinding fail permanently.
Distinguish a missing outgoing account from an existing account with no matching live token. A missing account only releases its ownership marker after the persisted account store is verified; the target write policy stays in force. A stale target now reports an account-selection instruction instead of a bare not-found error, including when takeover is already enabled.
Fixes#7392
Add Claude Desktop 3P configuration support on Linux. Resolve the config root from an absolute XDG_CONFIG_HOME, falling back to ~/.config; when CC Switch itself runs as a Flatpak, use the host ~/.config instead of the sandbox-private XDG_CONFIG_HOME. Update the en/zh/ja user manuals with Linux paths and the Flatpak boundary.
Fixes#4855
Zhipu's Responses endpoint (open.bigmodel.cn/api/v1) serves its model list in the Codex remote catalog shape (models[].slug) instead of the OpenAI-compatible data[].id shape, so the Codex form's model fetch came back empty. The parser now falls back to models[].slug when data is absent.
The tool version probe requested the full npm packument for each package (metadata for every historical version, 14-25 MB uncompressed for codex / opencode / openclaw) only to read its dist-tags, and it was the only latest-version probe without LATEST_PROBE_TIMEOUT, so it fell back to the proxy client's 600 s total timeout and the cards sat on "loading" for minutes on slow links while the large downloads starved the Hermes GitHub probe into "unknown".
Switch fetch_npm_dist_tags to registry.npmjs.org/-/package/{package}/dist-tags, whose body is the dist-tags object itself (tens of bytes to a few KB), escape scoped names as %2f, and apply the same 15 s probe timeout as the GitHub and PyPI probes. No data is lost: the only consumer reads latest and the tool's prerelease tags.
Fixes#7339
Show tokens/s next to the output token count in the request log table and the request detail panel.
The generation window prefers an explicit duration when present, otherwise latency minus first-token time for streaming requests, and falls back to full latency for non-streaming requests. Rows without a positive token count or window show nothing.
Closes#5936
DeepSeek retired V4 Flash and announced that V4 Pro is routed to V4.1
Flash and billed at the Flash price from 2026-09-14 12:00 (Beijing).
Executing that callback early per maintainer decision.
- Seed `deepseek-flash` (the only currently recommended id) and
`deepseek-v4-flash-vision-exp` so the `LIKE '{id}-%'` prefix fallback
cannot silently bill them at zero.
- Reprice `deepseek-v4-flash` / `-0731` / `-pro` to 0.3 / 1.2 / 0.006
with chained repair guards ordered after the 2026-08-16 peak/off-peak
rows; `deepseek-chat` / `deepseek-reasoner` stay untouched for lack of
an authoritative source.
- Drop `deepseek-v4-pro` from the confirmed text-only registry: it now
lands on a vision-capable model, so the image sanitizer must fail open.
Fixtures that relied on it being text-only switch to `qwen3-coder-plus`,
including the two media_sanitizer tests #7286 had just pointed at it.
DeepSeek's official endpoint now routes the legacy deepseek-v4-flash id to
the vision-capable V4.1 Flash, so #7286 removed it from the confirmed
text-only registry and the id fails open everywhere. Baidu Qianfan and
Tencent Token Plan still host the text-only V4 deployments (Qianfan's
Coding Plan doc states image input returns 400; Tencent's 2026-09-10 plan
rosters list V4 only), so their preset rows must carry an explicit
inputModalities: ["text"] declaration instead of relying on the registry.
Covers the flash and pro families incl. -0731/-0813/-202605/-202606 rows,
and adds a preset test that also locks the official DeepSeek preset to
stay undeclared (fail-open).
Follow-up to #7283.
Rename the DouBaoSeed provider preset across all seven app preset files
and localize its display name: zh/zh-TW show "火山 豆包AI", en/ja show
"Volcengine Doubao" via the new providerForm.presets.doubaoseed key.
Following the existing Qiniu/Compshare convention, the top-level name
holds the latin fallback (so the preset stays searchable in both
scripts) and the localized name lives in the locale files. OpenCode and
Pi settingsConfig.name, which is written into the client config files,
keeps the ASCII form.
Live-config identifiers are deliberately untouched: the Codex TOML
provider name, the Hermes node key doubao_seed, Pi's providerKey, the
OpenClaw model-ref prefix, partnerPromotionKey and icon.
Follow-up to #7219. The parser counted only fully consumed records toward
the persisted byte length, so a rollout that ends mid-record or in
whitespace (a crashed session that was never resumed) always looked
shorter than its file size and was fully reparsed on every sync pass.
Count the bytes of the incomplete tail as observed too. The line cursor
still stops before the incomplete record, so it is retried as soon as the
file grows, while an unchanged file is skipped on the mtime+size gate.
Tests prove the skip via total_changes() rather than a zero import count.
Since #6537 the tray deliberately dropped the usage suffix for Codex
official cards bound to a managed ChatGPT account: the tray only had an
app-wide subscription cache fed by whatever login the Codex CLI holds
(macOS Keychain first, then auth.json), which cannot represent
account-scoped quota safely once several accounts are bound. The provider
card queried the bound account through `get_codex_oauth_quota`, but that
result never reached the tray, so users with multiple ChatGPT logins saw
`Codex · <name>` with no quota at all.
- UsageCache: add an account-keyed `codex_oauth` snapshot map
(`put_codex_oauth` / `with_codex_oauth`), cleared by `invalidate_all`.
- `get_codex_oauth_quota`: write the `Ok` snapshot through to the cache
under the resolved account id and schedule a tray label refresh.
Transport errors keep the last good snapshot; auth/HTTP failures replace
it so the tray hides an invalid quota instead of a stale one.
- Tray: introduce `TrayUsageSource` so the refresh path and the display
path share one decision. Managed Codex cards read only their bound
account's snapshot (never a provider-scoped or CLI snapshot as fallback),
default to enabled when no usage toggle has been saved (matching
ProviderCard), and the fixed official card takes the managed path too
when it carries a binding. Rebinding a card switches to the new
account's snapshot immediately and a late response for the previous
account cannot overwrite the label.
- Tests: source selection across binding/toggle/legacy shapes, label
rendering across switch, rebind, late response, disabled and expired
states, and the native fixed card still using the CLI subscription.
Fixes#7267
Some third-party Anthropic-compatible gateways (e.g. DeepSeek) validate
tool JSON Schemas with a strict regex checker and reject the Unicode
property escapes (\p{Cc}...) that Claude Code's Artifact tool emits when
its str_replace db capability is rolled out, failing every request with
400 "Invalid schema for function 'Artifact'". The failure is independent
of the model selected.
Add a sixth checkbox next to the existing Claude quick toggles that sets
env.CLAUDE_CODE_DISABLE_ARTIFACT="1" on the provider, which keeps the
Artifact tool out of the tools array entirely. Unchecking removes the key
like the other toggles do. Labels added for zh/en/ja/zh-TW and the user
manual toggle table updated in zh/en/ja.
Both Kimi open platform (api.moonshot.cn/v1) and Kimi For Coding
(api.kimi.com/coding/v1) now serve /v1/responses natively and their
official Codex guides require wire_api = "responses", so the two presets
move from openai_chat (proxy Responses->Chat conversion, routing takeover
required) to openai_responses (Codex connects directly). Verified against
both endpoints with real keys using the exact Codex 0.153.4 request shape
(include reasoning.encrypted_content, reasoning.summary, hosted web_search,
replayed reasoning items) and with codex exec end-to-end tool loops.
- kimi-k3 becomes the default open-platform model and first catalog row;
kimi-k2.7-code stays as a second row (it also answers on /v1/responses,
although the OpenAPI only lists kimi-k3)
- drop codexChatReasoning (Chat-conversion only) from both presets and
promptCacheRouting from Kimi For Coding (Codex sends prompt_cache_key
itself on the native path; the proxy auto-detects the host anyway)
- declare supportsParallelToolCalls on every Kimi row, mirroring the
official Kimi Code models.json
- no reasoning default is declared: config.toml model_reasoning_effort
wins over the catalog default, which only marks the /model picker
- move the two presets from the Chat list to the native list in the
preset tests; invert the prompt-cache-routing assertion
- refresh the user manual (zh/en/ja) so the "Chat-only" examples name
providers that still use Chat routing, and correct the stale
userAgentPresets note about Kimi Code rejecting codex-cli
No backend change. Existing Kimi cards keep their stored openai_chat
format and continue to work through routing; switch a card's upstream
format to Responses (or re-add the preset) to connect directly.
The Claude OAuth usage API now reports model-scoped weekly limits in a
top-level `limits[]` array (`kind: "weekly_scoped"`, `scope.model.display_name`,
`percent`) instead of dedicated top-level windows. The parser only read the
legacy windows, so the Fable limit never showed up in the provider card or
the tray.
- Extract `parse_claude_quota` and parse `limits[]` into `seven_day_fable`,
`seven_day_opus` and `seven_day_sonnet`; scoped rows override the legacy
window of the same name, duplicates and malformed rows are skipped, and
legacy windows / extra usage / unknown windows are preserved.
- Tray: give Fable its own label group so it is not merged into the weekly
max value.
- Frontend: add the `seven_day_fable` label ("Fable") in all four locales.
- Tests: parser edge cases, tray summary for both quota and flattened script
paths, and footer rendering for inline/expanded layouts and locales.
Refresh the bundled DeepSeek official Codex catalog to the vendor's current models.json (slug deepseek-flash, image input modality, supports_image_detail_original) and remove deepseek-v4-flash from the confirmed text-only registry: the legacy id is still accepted by DeepSeek and routed to the vision-capable V4.1 Flash, so both the proxy media sanitizer and the generated Codex catalog must fail open for it. deepseek-v4-pro stays text-only per the vendor catalog.
Fixes#7283
The Responses API rejects max_output_tokens below 16, but Anthropic clients legitimately send tiny probe budgets (Claude Desktop's model-availability probe uses max_tokens=1). The Anthropic→Responses conversion copied the value verbatim, so strict upstreams returned 400 and Claude Desktop reported the mapped model as unavailable under local routing.
Clamp 1..=15 up to 16 during conversion; 16+, 0 and non-integer values keep their pass-through semantics. Normal session requests convert byte-for-byte as before, and the Codex OAuth path still strips max_output_tokens afterwards.
Fixes#7103
The Codex Responses -> Chat Completions converter emitted two consecutive
assistant messages when one Responses model turn contained a commentary
message directly followed by function_call items. Chat upstreams imitate
the text-only assistant message as a complete turn and return
finish_reason=stop before the expected tool call, so long agent tasks end
after a progress update.
Merge pending tool calls into the directly adjacent assistant message when
it carries no tool_calls yet, attach pending reasoning per segment so
parallel calls do not duplicate it, and keep the new-message path for every
other boundary shape (user/tool boundaries, prior tool-call batches, media
flushes). The reasoning placeholder backfill still applies to coalesced
calls without reasoning.
Fixes#6529
Supersedes #6530
Co-authored-by: BigStrongSun <BigStrongSun@users.noreply.github.com>
Some OpenAI-compatible upstreams (GLM, Qwen, DeepSeek-V4-Pro via ModelScope/DashScope,
Bailian, JD Cloud, ...) keep a `reasoning_content: ""` placeholder in every content
chunk instead of omitting the field. The reasoning branch of the OpenAI Chat -> Anthropic
SSE converter only checked for presence, and it shares `current_non_tool_block_type`
with the content branch, so every content chunk closed the open text block, opened an
empty thinking block, then reopened a text block. N content chunks became 2N content
blocks, half of them empty thinking blocks, which Claude Code rendered as one line per
token with dozens of empty Thought blocks and bloated the session JSONL.
Filter empty reasoning before entering the branch, matching the `!content.is_empty()`
guard the content branch already had and the non-streaming `openai_to_anthropic`
converter. Two regression tests pin block index, type and order: the placeholder shape
must yield a single text block and no thinking_delta at all, and real reasoning must
still yield one thinking block followed by one text block.
Fixes#5028Fixes#4404
Codex keeps the rollout append handle open for the whole session, so on Windows NTFS the file mtime does not advance while the file grows and the pure-mtime gate skipped growing rollouts forever. Persist the observed byte length in session_log_sync.last_byte_offset for Codex rows and skip a file only when both mtime and size are unchanged. The parser now splits records on newlines manually so an incomplete trailing record is retried on the next pass without advancing the line cursor.
Fixes#6060
* fix(codex): proxy image edits and Images API follow-ups
Follow-ups to #7036 for Codex's built-in ImageGen over the local proxy:
- Register `/images/edits` aliases (bare, `/v1`, `/v1/v1`, `/codex/v1`)
and forward them through the shared Codex standalone passthrough.
ImageGen posts to `images/edits` whenever a call references existing
images, and the router returned an empty 404 for it.
- Add `CodexStandaloneEndpoint::ImagesEdits`. Both Images endpoints share
one full-URL suffix table, so a complete Responses / Compact / Chat
Completions / Images URL derives the sibling endpoint (and vice versa)
while opaque full URLs keep failing closed.
- Apply the standalone sibling rewrite when the base URL is pasted as a
complete endpoint with the full-URL switch off, mirroring
`codex_chat_base_is_full_endpoint`; standalone requests no longer become
`.../chat/completions/images/generations`.
- Parse Images API streaming usage: `image_generation.completed` carries
`usage` on the event top level, so scan for `usage.input_tokens` before
falling back to the Chat Completions stream parser.
Related #7036
* fix(codex): match standalone URL suffixes case-insensitively
Keep endpoint detection and sibling rewriting consistent while preserving the original URL prefix and query. Cover mixed-case Images and Alpha Search endpoints through URL and proxy regression cases.
---------
Co-authored-by: thisTom <19346741+thisTom@users.noreply.github.com>
Co-authored-by: Jason <farion1231@gmail.com>
On normal exit, stop_with_restore_keep_state() called the legacy global
proxy-config writer to clear the long-retired live_takeover_active flag.
That writer reads the Claude row and runs an UPDATE without a WHERE clause,
so every shutdown copied Claude's max_retries and the three timeout fields
onto the Codex, Gemini and Grok Build rows — and the UPDATE never carried
live_takeover_active in the first place, so the step had no effect beyond
the clobber. The ephemeral listen-port path did the same on every proxy
start.
Drop the dead write-back (live-config restore, backup cleanup and health
reset are unchanged) and persist the resolved ephemeral port through the
global-config interface, which only touches the shared listen/logging
columns. Two regression tests seed distinct per-app settings for all four
apps and assert they survive both paths.
Fixes#7204
Syncing a universal provider regenerates its Claude/Codex/Gemini child
providers. The child's `settings_config` was merged with the existing row,
but `meta`, `created_at` and `sort_index` were taken from the generated
object, and the universal provider never carries any of them from the UI.
The UPDATE therefore wiped the child's usage script, common-config opt-out,
endpoint auto-select and other per-app settings to `{}` and reset the sort
index to NULL, which pushed the card to the bottom of the list and looked
like the provider had been deleted and re-created.
Keep the existing child's `meta`, `created_at` and `sort_index` when the
row already exists. Name, base URL, key, models, website and notes are
still driven by the universal provider, and first-time creation still
inherits the parent's metadata.
Fixes#7134
Rename the domestic Bailian presets to 千问AI平台 with a dedicated icon, refresh the Qwen family to the 3.8 generation across Claude Code, Claude Desktop, Codex, Hermes, OpenClaw, OpenCode and Pi, add the domestic Token Plan presets, restore the international QwenCloud Coding Plan presets, and align OpenClaw/OpenCode/Pi model metadata with the official client docs.
When a Codex provider card's TOML has no `model_provider`, Codex falls back to
its built-in `openai` provider, but takeover wrote the proxy address as a
top-level `base_url` that Codex never reads, so requests bypassed the local
proxy and went straight to api.openai.com.
Treat the missing selector as the built-in `openai` provider and write the
proxy address to `openai_base_url`; the existing legacy-reroute migration then
turns it into a `cc-switch` custom provider table carrying the `PROXY_MANAGED`
bearer, the same shape every other third-party takeover uses. Explicit
provider selections are unchanged.
Refs #6256, #7217
Atlas Cloud is no longer a sponsor. Drop the sponsor identity everywhere
while keeping the provider presets themselves intact:
- README (en/zh/ja/de): remove the Atlas Cloud row from the sponsor table
and delete the now-unreferenced banner image
- Presets (Claude Code, Claude Desktop, Codex, OpenCode, OpenClaw, Hermes,
Pi): strip `isPartner` / `partnerPromotionKey` from the AtlasCloud entry
and move it from the sponsor group to the non-sponsor group (endpoints,
models and icon unchanged)
- i18n (zh/en/ja/zh-TW): remove `providerForm.partnerPromotion.atlascloud`
SoleAPI (soleapi.com) joins as a sponsor, placed directly above Micu in
the sponsor order (preset files and the four README sponsor tables stay
in sync).
- Presets for Claude Code, Claude Desktop, Codex, Gemini CLI, Grok
Build, OpenCode, OpenClaw, Hermes and Pi. Endpoints follow the
vendor's CC Switch setup page: Anthropic/Gemini-style clients use the
bare host, OpenAI-style clients (Codex, Grok, Responses) use /v1.
- Haiku's upstream ID carries a date suffix
(claude-haiku-4-5-20251001), so the Desktop preset uses mappedRoutes
and the multi-model presets list the dated ID.
- Codex defaults to gpt-5.6-sol (vendor config.toml), Gemini to
gemini-3.8-flash.
- No OpenClaw/Hermes cost fields: site prices are official rates times
a per-channel multiplier and change with promotions.
- Referral link only in apiKeyUrl and README hrefs; request endpoints
stay bare.
- Inline currentColor icon traced from the vendor SVG, metadata entry,
four-locale partnerPromotion copy, and a 1920x786 banner.
Codex's built-in ImageGen switches from `/images/generations` to
`/images/edits` whenever it references existing images (explicit paths or
the last N generated images). After #7036 the generations route is proxied,
but edits still hit an empty local route and the tool fails with 404.
Add `CodexStandaloneEndpoint::ImagesEdits` and route the four local aliases
through the same standalone passthrough as generations. The full-URL sibling
derivation now uses a shared suffix table for the Images family, so a
provider configured with either `/images/generations` or `/images/edits` as
a complete URL derives the other route; opaque URLs still fail closed.
Tests cover the effective-endpoint match, full-URL rewrites in both
directions, and an end-to-end alias test that asserts auth replacement,
body preservation (data-URL images) and usage logging with the real Images
API `input_tokens_details` shape.