Skip to content

Releases: LeenHawk/gproxy

v1.0.22

27 May 06:28

Choose a tag to compare

v1.0.22

Vercel and Kiro join the built-in channel set, while Antigravity, Vertex, ClaudeCode, image streaming, and the provider console get a broad compatibility pass.

English

Added

  • Vercel AI Gateway channel. Added a vercel channel for OpenAI Chat Completions, Responses, Models, Embeddings, and Anthropic Messages / Count Tokens, plus console support for Vercel gateway source aliases via providerOptions.gateway.only. Vercel's Claude-shaped requests also support enable_magic_cache, flatten_system_before_cache, and cache_breakpoints.
  • Kiro / Amazon Q Runtime channel. Added a kiro channel backed by Kiro IDE 0.12.224's POST /generateAssistantResponse Smithy shape. Kiro-specific request conversion and AWS eventstream parsing stay inside kiro.rs; the channel supports non-streaming and streaming text generation through OpenAI Responses / Chat Completions, Claude Messages, and Gemini generateContent / streamGenerateContent, parses Kiro model-list responses, queries Kiro usage/quota through getUsageLimits, and uses local token counting.
  • Credential import improvements. Provider credentials can now be imported from one-key-per-line text, JSON objects, JSON arrays, or concatenated JSON payloads, with raw tokens mapped into the correct channel-specific credential field.

Fixed

  • Antigravity channel refresh. The built-in Antigravity channel now defaults to the production Cloud Code endpoint, advertises a current antigravity/2.0.1 user agent, requests the aicode OAuth scope, honors configured OAuth authorize/token/userinfo URLs, keeps image-generation / tiered model ids from fetchAvailableModels visible in normalized Gemini model-list responses, avoids forwarding Gemini pagination query params to fetchAvailableModels, sends count-token requests with Antigravity's {"request": ...} wrapper, and no longer advertises the unsupported embedding route.
  • Vertex OpenAI compatibility. Vertex model-list/model-get now route OpenAI clients through Gemini response conversion and send empty GET bodies to Google. Vertex OpenAI chat-completions also normalizes request bodies and accepts model ids returned by the model list.
  • ClaudeCode cookie bootstrap JSON stream parsing. Cookie/profile bootstrap now accepts Claude.ai responses that prepend a standalone JSON object before the real account payload, so profile switching still extracts the subscribed organization.
  • ClaudeCode credential cookie input. The admin console now normalizes pasted Cookie: headers and sessionKey=... strings to the raw session key before saving, so cookie bootstrap sends a usable Claude.ai session cookie.
  • OpenAI image endpoint request transforms. OpenAI-compatible /v1/images/generations and /v1/images/edits bodies now convert through the raw request-body path before routing to Responses/Gemini backends, avoiding local 500s on Codex image-generation compatibility calls.
  • OpenAI image endpoint response aggregation. Non-stream OpenAI-compatible image requests that route through Responses streaming now aggregate upstream SSE before converting back to /v1/images/generations, so successful Codex image generations no longer return 500 during response conversion.
  • ClaudeCode Responses stream aggregation usage. Non-stream ClaudeCode requests routed to OpenAI Responses streaming now preserve Responses usage counts while returning Claude Messages usage with explicit null stop metadata, global inference geography, and no empty server_tool_use object.
  • Vercel credential health on payment failures. Vercel AI Gateway 402 Payment Required responses now invalidate the credential like 401 / 403, allowing retry rotation to skip exhausted keys.
  • Provider console fixes. Credential rows now show stable credential ids, request-log filters use the same ids, deleting rewrite rules persists immediately, and cache breakpoint TTL tags returned as ttl5m / ttl1h render as 5m / 1h instead of auto.

Changed

  • ClaudeCode fingerprint editor. The admin console now renders fingerprint as a localized client-fingerprint editor instead of a raw JSON textarea, with explicit fields for Claude Code and x-stainless-* request identity values.
  • Channel response classification. Channel response handling now exposes richer success/auth/rate-limit/transient/permanent classification so providers can invalidate or rotate credentials for provider-specific failures.
  • Dependency refresh. Updated the npm documentation/tooling dependency set, including Astro.

简体中文

新增

  • Vercel AI Gateway 渠道. 新增 vercel 渠道,支持 OpenAI Chat Completions、Responses、Models、Embeddings 以及 Anthropic Messages / Count Tokens;控制台后缀别名也支持通过 providerOptions.gateway.only 选择 Vercel gateway 来源。Vercel 的 Claude 形态请求也支持 enable_magic_cacheflatten_system_before_cachecache_breakpoints 设置。
  • Kiro / Amazon Q Runtime 渠道. 新增基于 Kiro IDE 0.12.224 POST /generateAssistantResponse Smithy 形状的 kiro 渠道。Kiro 专有请求转换和 AWS eventstream 解析都收在 kiro.rs 内,支持通过 OpenAI Responses / Chat Completions、Claude Messages、Gemini generateContent / streamGenerateContent 做非流式与流式文本生成,解析 Kiro 模型列表响应,通过 getUsageLimits 查询 Kiro usage/quota,并使用本地 token 计数。
  • 凭证导入增强. Provider 凭证现在支持按行粘贴 key、JSON object、JSON array 或连续 JSON payload 导入,原始 token 会按渠道自动写入正确的凭证字段。

修复

  • Antigravity 渠道刷新. 内置 Antigravity 渠道现在默认使用正式 Cloud Code 端点,发送当前 antigravity/2.0.1 User-Agent,OAuth scope 加上 aicode,后端会实际使用配置里的 OAuth authorize/token/userinfo URL,会把 fetchAvailableModels 中的生图 / tiered model id 保留到标准 Gemini 模型列表响应里,不会再把 Gemini 分页 query 透传给 fetchAvailableModels,count-token 请求会使用 Antigravity 实际接受的 {"request": ...} wrapper,并且不再暴露不支持的 embedding 路由。
  • Vertex OpenAI 兼容性. Vertex 的 model-list/model-get 现在会把 OpenAI 客户端路由到 Gemini 响应转换,并向 Google 发送空 GET body;Vertex OpenAI chat-completions 也会规范化请求体,并接受模型列表返回的模型 ID。
  • ClaudeCode cookie bootstrap JSON stream 解析. cookie / profile bootstrap 现在能接受 Claude.ai 在真实 account payload 前返回独立 JSON 对象的响应,切换 profile 时仍能提取订阅组织。
  • ClaudeCode 凭证 cookie 输入. 管理控制台现在会把粘贴的 Cookie: header 或 sessionKey=... 字符串规范化成裸 session key 后再保存,确保 cookie bootstrap 发出可用的 Claude.ai session cookie。
  • OpenAI 图像端点请求转换. OpenAI 兼容的 /v1/images/generations/v1/images/edits 请求体现在会按原始 body 转换后再路由到 Responses / Gemini 后端,避免 Codex 图像生成兼容调用在本地转换阶段返回 500。
  • OpenAI 图像端点响应聚合. 路由到 Responses streaming 的非流式 OpenAI 兼容图像请求现在会先聚合上游 SSE,再转换回 /v1/images/generations 响应,避免 Codex 成功生成图片后在响应转换阶段返回 500。
  • ClaudeCode Responses stream 聚合用量. 路由到 OpenAI Responses streaming 的非流式 ClaudeCode 请求现在会保留 Responses usage 计数,同时返回带显式 null stop 元数据、global 推理区域且不含空 server_tool_use 对象的 Claude Messages usage。
  • Vercel 支付失败时的凭证健康状态. Vercel AI Gateway 返回 402 Payment Required 时现在会像 401 / 403 一样将凭证判为失效,让重试轮换跳过额度耗尽的 key。
  • Provider 控制台修复. 凭证列表现在展示稳定 credential id,请求日志筛选也使用同一套 id;删除 rewrite rule 会立即持久化;API 返回的 ttl5m / ttl1h cache breakpoint 会显示为 5m / 1h,不再误显示成 auto

调整

  • ClaudeCode 指纹编辑器. 管理控制台现在把 fingerprint 渲染成本地化的客户端指纹编辑器,不再只是原始 JSON 文本框;Claude Code 和 x-stainless-* 请求身份字段都有独立输入项。
  • 渠道响应分类. Channel response handling 现在能返回更细的 success/auth/rate-limit/transient/permanent 分类,让 provider 可以按上游特定错误失效或轮换凭证。
  • 依赖刷新. 更新 npm 文档 / 工具链依赖,包含 Astro。

staging

01 Mar 15:35

Choose a tag to compare

staging Pre-release
Pre-release

Automated staging build from e2406e2701b93a12e24f6a41b10da0fe98efdd07.

v1.0.21

10 May 10:55

Choose a tag to compare

v1.0.21

Protocol packaging is split out, provider/admin behavior is tightened, and several channel compatibility fixes land together.

English

Added

  • Standalone gproxy-protocol repository integration. The protocol crate is now wired as a standalone repository/submodule and the CI/release workflows fetch it explicitly. Workspace and admin API docs were updated to match the new layout.
  • Update-channel configuration. Added storage/API support for configuring the update channel, including the migration and admin settings plumbing.
  • Credential rotation strategy. Providers can now choose the credential rotation strategy, with console labels and option text localized.
  • Credential copy affordance. The admin console adds copy actions with visible success feedback for credential fields.

Fixed

  • ClaudeCode fingerprint settings are now the single UA source. The console exposes fingerprint JSON settings, and normal requests, quota requests, OAuth profile/token exchange, token refresh, and cookie bootstrap all derive their UA from the same fingerprint.cli_version / user type / entrypoint settings. The old console user_agent default and backend hard-coded UA values were removed (#95).
  • ClaudeCode OAuth/cookie bootstrap compatibility. Cookie bootstrap filters organizations by subscription capability and sends the required OAuth beta headers during the authorize step.
  • DeepSeek no longer prepends /v1 to upstream paths. Model list/get and chat/responses requests now use DeepSeek's root API paths while Anthropic-compatible paths keep their own prefixing behavior.
  • Vertex CountToken/OpenAPI handling. Vertex request body handling is stricter and OpenAPI chat-completions compatible requests route to the correct endpoint.
  • Structured-output conversion cleanup. OpenAI-to-Claude transforms drop deprecated output_format, avoid unsupported permissive JSON-object shims, and keep schema serialization strict.
  • TOML export for rewrite rules. Model alias/suffix rewrite rules no longer export empty filter dimensions as JSON null, avoiding unsupported unit type during config export (#94).
  • Responses/image stream schema tolerance. Responses keepalive events and partial image-generation output items are accepted instead of turning valid upstream streams into local 500s.

Changed

  • Documentation refresh. Quick-start and SDK/admin references now point at the current workspace, release download flow, and protocol layout.
  • Console polish. Rotation-strategy labels are simplified and localized, and dark-theme toast styling is readable.

简体中文

新增

  • gproxy-protocol 独立仓库接入. protocol crate 已拆到独立仓库 / submodule,CI 与 release workflow 会显式拉取;workspace 与 admin API 文档同步更新到新布局。
  • 更新渠道配置. 新增 update channel 的存储 / API / admin settings 管线,包含数据库迁移。
  • 凭证轮换策略. Provider 可配置 credential rotation strategy,控制台标签和选项文案已完成中英文。
  • 凭证复制反馈. 管理控制台给凭证字段增加复制动作,并显示明确的成功反馈。

修复

  • ClaudeCode fingerprint settings 成为 UA 唯一来源. 控制台现在暴露 fingerprint JSON 配置;普通请求、quota、OAuth profile/token exchange、token refresh、cookie bootstrap 都从同一组 fingerprint.cli_version / user type / entrypoint 派生 UA。移除了旧的控制台 user_agent 默认值和后端硬编码 UA(#95)。
  • ClaudeCode OAuth / cookie bootstrap 兼容性. cookie bootstrap 会按订阅能力筛选 organization,并在 authorize 步骤发送必需的 OAuth beta headers。
  • DeepSeek 上游路径不再拼 /v1. Model list/get、chat/responses 请求现在走 DeepSeek 根路径;Anthropic 兼容路径继续保持自己的前缀规则。
  • Vertex CountToken / OpenAPI 处理. Vertex 请求体处理更严格,OpenAPI chat-completions 兼容请求会路由到正确端点。
  • 结构化输出转换清理. OpenAI → Claude 转换删除废弃的 output_format,避免生成上游不支持的宽松 JSON-object shim,并保持 schema 序列化严格。
  • rewrite rules TOML 导出. 模型别名 / 后缀变体自动生成的 rewrite rules 不再把空 filter 维度导出成 JSON null,避免配置导出时报 unsupported unit type(#94)。
  • Responses / image stream schema 兼容. Responses keepalive 事件和 image-generation 的 partial output item 现在会被接受,不再把有效上游流误转成本地 500。

调整

  • 文档刷新. Quick Start、SDK、admin API 参考已对齐当前 workspace、release 下载流程和 protocol 布局。
  • 控制台细节. rotation strategy 标签简化并本地化,dark theme toast 样式可读性修正。

v1.0.20

24 Apr 06:10

Choose a tag to compare

v1.0.20

ChatGPT 渠道重构

  • system_hints 透传 + model 后缀工具别名:OpenAI 兼容请求体可通过三种方式触发 chatgpt.com 内置工具 —— 原始 id {"system_hints":["picture_v2","search"]}extra_body.tools_hint 友好别名、以及 model: "gpt-5@image" 的尾缀语法;后缀表覆盖 image / search / study / agent / canvas / connectors / company / deep-research / quiz
  • 硬编码工具映射迁移到 rewrite_rules:删除 Rust 侧 TOOL_SUFFIXES@<tool>/:<tool> 解析器、tools_hint 友好别名、以及 resolve_model 里的 gpt-5/gpt-5-thinking/gpt-5-pro/gpt-5-instant 重映射 —— 这些能力现在完全由数据驱动的 rewrite_rules 实现,可在管理控制台里配置
  • 去掉独立 chatgpt 预设协议:后缀变体(image-gen / web search / deep research)改为输出标准 OpenAI Responses-API 形状(tools: [{type}] + tool_choice),同一条 DB 别名可跨 codex / openai(透传)与 chatgpt(翻译)复用
  • 工具类型提取扩展:chatgpt 的 extract_system_hints 现在同时读 body.tools[*].type,把 image_generation → picture_v2、web_search[_preview] → search、deep_researchconnector:connector_openai_deep_research;未知 tool 类型在 chatgpt 路径上静默丢弃

模型 & 计费

  • DeepSeek V4 上线:上游精简为 deepseek-v4-flash / deepseek-v4-pro 两个模型,deepseek-chat / deepseek-reasoner 保留为兼容别名,分别映射到 flash 的非思考 / 思考模式;前端 PRICING_TEMPLATES 同步更新
  • gpt-5.5 系列模型与定价data/models/ JSON 文件新增 gpt-5.5 系列条目与定价结构

协议与引擎修复

  • 保留上游 meta 即便流聚合 / 转换失败execute_inner 捕获的 upstream status + body + latency 之前会被 aggregate_stream_body? / transform_response? 的 blanket From<TransformError> 推入 ExecuteError::bare(meta: None),导致 admin 上游日志显示 500 / 空响应 / 0ms。现在统一通过 map_errUpstreamRequestMeta 附到转换失败路径上,schema 漂移等错误有完整取证
  • Responses API keepalive SSE 帧:Codex 后端中途下发 event: keepalive,不在 OpenAI 公开的 Responses 流式规范里,之前被 tag-discriminated 枚举拒绝,整个 SSE 变 500。给 ResponseStreamEvent / ImageGenerationStreamEvent / ImageEditStreamEvent 补 Keepalive 变体
  • image_generation_call 输入 / 输出 schema 分离:response.output_item.added 帧里的 image_generation_call 只有 {id,type,status}(还没结果),之前复用了要求 result: String 的 count_tokens 输入类型导致解析失败。新增 ResponseOutputImageGenerationCall:result: Option<String> 并带 Codex 运行时元数据(action / background / output_format / quality / size / revised_prompt),输入类型保持规范严格

ClaudeCode

  • magic cache_control 跳过 thinking 块(同步 sgproxy 676c86c):thinking / redacted_thinking 块不能携带 cache_control,注入阶段跳过,计数阶段也不占 4 槽上限
  • 保留 speed 字段:移除 normalize_claudecode_unsupported_fields —— speed 原样透传给上游

其他

  • CodeQL 代码质量扫描工作流
  • OpenRouter base_url 修正:前端 channel-forms 去掉多余版本号段
  • astro 6.1.5 → 6.1.9:修 GHSA-j687-52p2-xcff (CVE-2026-41067, define:vars XSS);docs 站静态构建未暴露,仅清理告警
  • ChatGPT 集成测试清理:tests/chatgpt_stream_pipeline.rsinclude_bytes! 引用 target/samples/ 里未入库的 HAR 导致新 checkout 编译失败,连同 tests/chatgpt_live_e2e.rs(需 live 访问 + access token)一并删除;活跃回归覆盖继续放在 target/scripts/ 本地 Python harness

v1.0.19

22 Apr 17:00

Choose a tag to compare

v1.0.19

新渠道:ChatGPT Web

  • 全新接入 ChatGPT Web 渠道:PoW、prepare_p、sentinel、SSE v1 解码与 OpenAI chunk 转换
  • 对话默认走 temporary chat(可通过渠道设置关闭)
  • 图像生成 + /v1/images/edits(三步上传 + asset pointer)
  • 本地 model list / model get / count_tokens,支持动态模型列表与别名映射(用于 picker UI 名称)
  • 转发 thinking_effort/f/conversation
  • 支持 cookie_store 与 spoof client 刷新
  • Console 前端集成:图像生成、temporary_chat 本地化、粘贴原始 token 自动包装为 {access_token}
  • 信任调用方传入的 model slug;未知模型回退默认值
  • StreamReshaper hook 替代旧实现,并将 reshape 迁入 normalize_response
  • 在剩余 channel dispatch 与 provider store dispatch 中补齐 chatgpt 注册

Model List / ModelGet

  • URL query 提升为一等请求字段
  • 跨协议 ModelList 翻译,覆盖全部 channel
  • 本地 + 上游合并返回,采用复合 pageToken
  • 针对 Claude / OpenAI 客户端的协议感知分页
  • ModelGet 的 model_id 允许包含 /,支持带 vendor 前缀的模型 id

修复

  • Alias:模型解析按 provider 作用域(#90
  • Log:重定向后记录最终 upstream URI(#89
  • Protocol:transform_request 正确透传 model,使 Gemini 跨协议工作
  • Router:修正 count tokens 端点路径
  • Console:保存 provider 时路由名不得为空;仅在模板展开时显示模板提示

其他

  • OpenRouter:新增响应归一化与错误 reshape
  • README:强调 DB 不存在时 TOML 仅读取一次
  • ChatGPT 代码格式清理与可读性改进

v1.0.18

21 Apr 04:38

Choose a tag to compare

v1.0.18

Streaming usage 端到端打通(stream_options.include_usage 自动注入 + 所有跨协议流式路径都观察上游 usage),mimalloc 接管全局分配器,缓存流水线重排为 magic → rules → flatten 并用 sanitize 统一清理空块/空消息 + 自动把 cache_control 回迁到最近可缓存块,context-1m-2025-08-07 beta 在 anthropic / claudecode 渠道默认剥离,一次性迁移扫掉指向已废弃 realtime 变体的 routing 规则,控制台新增「恢复默认路由」按钮。

English

Added

  • Upstream streaming usage tracking. The engine now observes and records upstream usage on streaming requests across every cross-protocol path, not just the non-streaming ones. OpenAI Chat Completions streaming requests have stream_options.include_usage = true injected automatically so the final usage frame is always emitted, and usage is pulled out and persisted alongside the existing non-stream accounting.
  • mimalloc as the global allocator. The main binary now pins mimalloc via #[global_allocator]. Measurable improvement in steady-state memory footprint and fragmentation under the fan-out-heavy streaming workload this proxy actually runs; no code-side API changes.
  • "Restore default routing" button on the provider workspace. One click resets the current provider's routing_json back to the channel's built-in routing table — the recovery path for anyone who edited the table by hand and wants to get back to a known-good state without deleting the provider.
  • "+ Add Alias" button in the models pane. Sits next to "+ Add Suffix Variant". Opens a minimal dialog asking only for a free-form alias name (prefilled with {base.model_id}-), and on confirm creates a standalone model row plus a single path:"model" set <real> rewrite rule scoped to the alias. Use this when you just want a name — no thinking / reasoning / effort preset injection.
  • claudecode default version + fingerprint. The default bundled claudecode version is bumped and the fingerprint/attribution settings are extended.

Fixed

  • Sidebar credential count refreshes after add / delete. The provider list's "N creds" badge is ProviderRow.credential_count from /admin/providers/query, but CredentialsPane only called onProviderScopedReload after a credential upsert/delete — that refreshed the credential + status rows but left the provider list stale until the next manual reload. Now threads onReloadProviders through and fires it alongside the scoped reload, so the badge updates in-place.
  • Startup no longer fails on DBs that briefly ran the realtime branch. A one-shot sea-orm-migration rewrites providers.routing_json and drops any rule whose source or TransformTo destination operation references a realtime variant (openai_realtime_websocket, realtime_client_secret_create, realtime_call_{accept,hangup,refer,reject,create}). Before this migration those rows would fail serde with unknown variant 'openai_realtime_websocket', expected one of … on boot. Run-once via seaql_migrations; safe on fresh DBs.
  • Empty / whitespace-only content blocks no longer waste cache breakpoints. finalize_request now drops whitespace-only text blocks, empty content arrays, and empty messages. When a removed block carried cache_control, the marker is shifted to the most recent surviving cacheable block — first within the same message scope, then scanning back through earlier kept messages. The magic-trigger space-pad hack is gone: sanitize handles the residue uniformly, which removes ~130 lines of special-case paths.
  • claude_cache_control::sanitize_block_array simplified. Cache-control handling in the block-array sanitizer is collapsed to a single pass, matching the semantics used elsewhere in the module.
  • claudecode billing attribution format. Removed an unused CCH hex length constant and corrected the attribution format.

Changed

  • Cache pipeline reordered: magic → rules → flatten. Rule indices and magic-string positions both depend on the original block layout, so flatten now runs last. cache_control placed by the earlier passes is inherited by the merged block via flatten's last-cc-wins rule — same breakpoints land in the same places, with strictly fewer wire blocks.
  • Magic-string cache breakpoint simplified on empty text. Replaced the cascading drop-block / bubble-to-previous logic with a single space pad when a magic trigger strips its text block to empty. Claude still accepts the block, the breakpoint lands in place, and the removed special-case paths become ~130 lines shorter.
  • context-1m-2025-08-07 beta stripped by default on anthropic + claudecode. Anthropic currently rejects the 1M-context beta on these channels; finalize_request strips the header before merging operator-supplied extra_beta_headers, so operators can still opt back in explicitly if upstream re-enables it.
  • Instruction joining: double newline → single space. Multiple instruction segments (OpenAI Responses → Claude path and friends) are now joined with a single space instead of \n\n, and the surrounding instruction-handling code in the OpenAI Response conversion is simplified.
  • Console muted-text contrast. Bumped --muted from slate-600 → slate-700 (light) and slate-400 → slate-300 (dark) so the 12px module-top hint bars read comfortably over the gradient surfaces.
  • Usage flag insertion streamlined. stream_options.include_usage insertion in the engine is rewritten into a single small branch.

UI / i18n

  • Provider route shown as path, model display name promoted. The provider list entry now renders the route as its path, and the model's display name takes the primary slot.
  • "Provider name" relabeled to "Route name". The field was never the channel-type name — it is the route identifier. Both locales updated.

Compatibility

  • Drop-in upgrade from v1.0.17. The realtime-routing cleanup migration runs on first boot via seaql_migrations; fresh DBs skip it.
  • SDK / protocol consumers: no protocol surface changes. Streaming upstream usage is additive — non-streaming behavior is unchanged, and streaming responses still pass through chunk-by-chunk.
  • context-1m-2025-08-07 opt-back-in: if you need the 1M-context beta on an anthropic / claudecode channel, add it explicitly via the provider's extra_beta_headers — the default strip applies before the merge, so operator-supplied values still win.

简体中文

新增

  • 上游流式 usage 追踪. 引擎现在在所有跨协议流式路径上都观察并记录上游 usage,不再只覆盖非流式路径。OpenAI Chat Completions 流式请求会自动注入 stream_options.include_usage = true,保证最终那一帧 usage 一定被发出;usage 在流结束时落入与非流式同一套计费账目。
  • mimalloc 接管全局分配器. 主二进制用 #[global_allocator] 固定到 mimalloc。对本 proxy 实际跑的"高扇出流式"工作负载,稳态内存占用和碎片有可观的改善;对代码侧 API 零改动。
  • Provider 工作区新增「恢复默认路由」按钮. 一键把当前 provider 的 routing_json 重置回 channel 的内置路由表 —— 留给那些手改过路由表又想回到已知良好状态的人,不用删 provider 重建。
  • 模型列表新增「+ 添加别名」按钮. 紧挨着「+ 添加后缀变体」。弹出一个极简对话框,只要求填自由别名(预填 {base.model_id}-),确认后创建一行独立 model + 一条 path:"model" set <真名> 改写规则(model_pattern = 别名)。适用于"只想起个名、不要注入 thinking / reasoning / effort 预设"的场景。
  • claudecode 默认版本和 fingerprint 升级. 内置的 claudecode 版本号升级,fingerprint / attribution 相关设置扩展。

修复

  • 凭证增删后 sidebar 凭证数量 badge 立即刷新. provider 列表上的 "N creds" 来自 /admin/providers/query 返回的 ProviderRow.credential_count,但 CredentialsPane 在 upsert/delete 成功后只调了 onProviderScopedReload(刷凭证详情 + 状态),provider 列表那份计数不跟着走,要手动刷新才会更新。现在把 onReloadProviders 一并传下去,和 scoped reload 一起触发,badge 立即同步。
  • 短暂跑过 realtime 分支的 DB 启动不再失败. 新增 sea-orm-migration 一次性改写 providers.routing_json,剔除任何 source 或 TransformTo 目标 operation 指向 realtime 变体(openai_realtime_websocketrealtime_client_secret_createrealtime_call_{accept,hangup,refer,reject,create})的规则。迁移前这些行会在启动时 serde 报 unknown variant 'openai_realtime_websocket', expected one of …。通过 seaql_migrations 记录只跑一次;新库会跳过。
  • 空 / 纯空白内容块不再浪费缓存断点. finalize_request 现在会扔掉纯空白 text 块、空 content 数组和空 message。被扔的块上如果带 cache_control,断点会转移到最近一个仍然存活的可缓存块 —— 先在同 message 作用域内找,再向前跨 message 回溯已保留的块。之前 magic-trigger 打空格 padding 的 hack 一并删掉:sanitize 统一处理残块,省掉约 130 行特殊分支。
  • claude_cache_control::sanitize_block_array 简化. block array sanitizer 里的 cache_control 处理收敛为单趟,与 module 其它位置的语义一致。
  • claudecode 计费 attribution 格式. 删除未使用的 CCH hex 长度常量,attribution 格式修正。

变更

  • 缓存流水线顺序调整:magic → rules → flatten. 规则索引和 magic 字符串位置都依赖 原始 块布局,所以 flatten 放到最后。前两步放上去的 cache_control 在 flatten 里按 last-cc-wins 合并到结果块里 —— 断点落位完全一致,线上块数严格更少。
  • magic-string 空文本断点处理简化. 之前的"扔块 / 冒泡到上一块"级联逻辑,替换为 magic trigger 把文本清空后补一个空格。Claude 仍然接受该块,断点落在原位,删掉的特殊分支约 130 行。
  • anthropic + claudecode 默认剥离 context-1m-2025-08-07 beta. 上游当前在这两个渠道上拒绝 1M 上下文 beta;finalize_request 在合并 operator 侧 extra_beta_headers 之前就剥掉这条,上游放开之后运维还能显式塞回去。
  • instruction 拼接:双换行 → 单空格. 多段 instruction(OpenAI Responses → Claude 路径等)拼接从 \n\n 改为单空格;OpenAI Response 转换里相关的 instruction 处理代码同步简化。
  • 控制台 muted 文案对比度. --muted 由 slate-600 → slate-700(light)/ slate-400 → slate-300(dark),12px 的模块顶部提示条在渐变背景上读起来更舒服。
  • usage flag 注入简化. engine 里 stream_options.include_usage 注入收敛为一小段分支写法。

UI / i18n

  • provider 路由以 path 展示,模型 display name 升为主字段. provider 列表条目现在把 route 当作路径渲染,主位让给模型的 display name。
  • "provider name" 文案改为 "route name". 这个字段从来不是 channel 类型名,是路由标识。中英文同步更新。

兼容性

  • 从 v1.0.17 直接升级。realtime 路由清理迁移通过 seaql_migrations 在首启时跑一次;新库会跳过。
  • SDK / protocol 调用方:无协议表面变化。流式 upstream usage 是增量改动 —— 非流式行为不变,流式仍然按 chunk 直通下发。
  • context-1m-2025-08-07 显式启用方式:如果你确实需要在 anthropic / claudecode 渠道打开 1M 上下文 beta,请通过 provider 的 extra_beta_headers 显式添加 —— 默认剥离发生在合并之前,运维显式配置仍然胜出。

v1.0.17

17 Apr 14:54

Choose a tag to compare

v1.0.17

The suffix-variant rewrite pipeline is repaired end-to-end: the engine was passing &[] as the rewrite rule slice, the handler was letting alias resolution replace the user-sent model name (so model_pattern never matched), and body.model = "provider/variant" from OpenAI-style clients rode the provider/ prefix straight into the filter. All three are fixed — a request to claudecode/claude-opus-4-7-thinking-adaptive-effort-max now actually reaches Anthropic with thinking.display = "summarized", output_config.effort = "max", and model = "claude-opus-4-7". The models table is flattened in the same pass: alias_of is dropped, every model is a standalone row, and the DB migration takes care of existing aliases in place. Plus cache-control gets a new flatten_system_before_cache toggle, a few breakpoint-shifting bug fixes, and the console's boolean settings get an iOS-style slide switch.

English

Added

  • flatten_system_before_cache channel setting (claudecode / anthropic). When the request's system is a list of text blocks, the blocks are concatenated into a single text block before cache breakpoints run. This undoes Claude Code's habit of splitting a stable system prompt across many small blocks, which was preventing the cache-breakpoint planner from reliably tagging the prompt as cacheable. Off by default; flip it on for claudecode-forwarded traffic where cache hit rate matters.
  • Status toggle turns into a slide switch. StatusToggle is restyled as an iOS-style slide switch (grey track + white knob that slides on/off, green when on). Replaces the previous dot-and-badge design. Applied to GlobalSettingsModule's five flags and ConfigTab's two cache booleans (enable_magic_cache, flatten_system_before_cache) — the boolean channel settings in ConfigTab are now switches instead of a false/true dropdown.
  • Migration m20260417_000001_drop_models_alias_of. Drops the alias_of column on the models table. Runs at most once per DB (tracked in seaql_migrations); a fresh DB skips it because entity sync creates the table without the column in the first place.

Fixed

  • Executor actually applies rewrite_rules now. engine.execute / engine.execute_stream were calling apply_outgoing_rules(&mut prepared, &provider.sanitize_rules(), &[]) — the rewrite slice was hard-coded empty. Sanitize rules ran, rewrite rules never did. This silently broke every suffix-variant recipe in the console: you could author model_pattern = "…-thinking-adaptive-effort-max"path:"thinking" set {display, type} / path:"output_config" set {effort:"max"} / path:"model" set "claude-opus-4-7" rules, save them, and watch the upstream body come out untouched. Fixed by passing &provider.rewrite_rules(). The outbound body for a claude-opus-4-7-thinking-adaptive-effort-max request now correctly reflects every applicable rule.
  • Handler strips the {provider}/ prefix from body.model before alias / permission / rewrite lookups. OpenAI-style clients conventionally send body.model = "claudecode/claude-opus-4-7-thinking-adaptive-effort-max". The prefixed string rode straight into resolve_model_alias, the permission check, ExecuteRequest.model, and ultimately the executor's model_pattern filter — where every stored suffix-variant rule is authored against the bare name, so nothing matched. Strip the matching {provider}/ prefix once at handler entry; all downstream matching now sees the same bare key.
  • Handler no longer lets alias resolution overwrite the model name. Alias resolution used to replace effective_model with the target model's model_id (e.g. claude-opus-4-7-thinking-adaptive-effort-maxclaude-opus-4-7) before the body ever reached the executor. That killed model_pattern matching for every suffix-variant rule by the time rewrite_rules ran. Alias resolution now contributes only the provider route; the user-sent model name stays in effective_model end-to-end. The suffix variant's own path:"model" set "<real>" rewrite rule takes over the body-side rename at the correct pipeline position (after protocol translation, before send).
  • cache_control: empty system messages and magic-trigger stripping no longer waste breakpoints. Three related fixes: (1) flatten_system_text_blocks drops empty text blocks and shifts cache breakpoints up one index if the removed block was already tagged; (2) magic-string triggers whose replacement empties the block now shift the breakpoint to the next non-empty block instead of pointing at a deleted slot; (3) apply_magic_string_cache_control_triggers helper tightened to one call path instead of two (pure cleanup). End result: no more "silent cache miss because the breakpoint pointed at a removed block" regressions.
  • Console preserves i64 trace ID precision. trace_id / downstream_trace_id / cursor_trace_id values (and the trace_ids array on batch-delete) can exceed 2⁵³, which silently rounds the last digits through JavaScript's Number. The console now pre-processes JSON responses to quote those fields as strings before JSON.parse, and reverses the quoting when building request bodies — the precise 18-19 digit ID survives display, copy/paste, cursor-based pagination, and batch-delete round-trips. No backend change required.

Changed

  • Models table flattened: alias_of indirection dropped. Suffix variants used to be model rows carrying an alias_of pointer to the "real" model; resolve_model_alias followed that pointer and returned the target's (provider_name, model_id). The indirection duplicated what rewrite_rules already do — every alias row was already paired with a path:"model" set <real> rule and already stored the right provider_id. After this release: every model, suffix-variant or not, is a standalone row; resolve_model_alias returns the row's own (provider_name, model_id); body-side model translation is done by rewrite_rules end-to-end. Existing alias rows are kept in place by the migration — the column drop is lossless because each row already carries the right provider_id and variant name. Frontend follows: the only_aliases / only_real filter tabs, the alias-target picker, the alias badge, and the alias "→ target" link in the model list are all removed; the "+ Add Suffix Variant" button is now available on any model. No TOML [[model_aliases]] section anymore; they were redundant with [[models]].
  • i18n: enable_magic_cache label renamed to "Enable Cache Magic String" (both locales). Clarifies that the setting gates the magic-string trigger pass, not cache in general.
  • Two unrelated loop / iterator cleanups. apply_credential_updates drops a redundant .into_iter() argument to zip, and batch_upsert_models simplifies its item loop. Pure readability.

Compatibility

  • Drop-in upgrade from v1.0.16. The DB migration runs on first boot; no manual data work is needed.
  • Suffix-variant aliases created in earlier versions keep working. The rows themselves are kept — migration drops only the alias_of column — and their provider_id + model_id = variant-name already make them valid standalone model entries under the new routing.
  • TOML config format: [[model_aliases]] is gone. Suffix variants now belong under [[models]]. If your config exports still include [[model_aliases]], they'll fail to parse; remove the section (existing DB rows are already flat).
  • Console JSON payloads for rewrite rules now carry trace IDs as strings. If you have external tooling scraping the admin requests/*/query APIs, it needs to accept string trace IDs (both numbers and strings are accepted on the wire by the backend, so there's no serializer change server-side — this is a frontend-only behavior).
  • SDK / protocol consumers: no protocol surface changes.

简体中文

新增

  • flatten_system_before_cache 渠道开关(claudecode / anthropic)。 当请求的 system 是一串 text block 时,缓存断点逻辑运行前把这些块合并成一个 text 块。专治 Claude Code 把一个稳定的系统提示拆成多个小块、导致缓存断点规划命中率低的情况。默认关闭,对转发 claudecode 流量且关心缓存命中率的部署再打开。
  • 状态开关改成左右滑的"滑动开关"。 StatusToggle 重新样式化为 iOS 风格滑动开关(灰色 track + 白色 knob,开启时 track 变绿、knob 右滑),替换原来的"小圆点 + 徽章"。GlobalSettingsModule 里五个开关和 ConfigTab 的两个缓存布尔开关(enable_magic_cacheflatten_system_before_cache)都跟着变;ConfigTab 的布尔设置不再是 false/true 下拉,直接就是滑动开关。
  • 迁移 m20260417_000001_drop_models_alias_of 删除 models 表的 alias_of 列,每个 DB 至多跑一次(记录在 seaql_migrations 表)。全新 DB 会跳过,因为 entity sync 创建表时就已经不带该列。

修复

  • executor 真正应用 rewrite_rules 了。 engine.execute / engine.execute_stream 之前调用 apply_outgoing_rules(&mut prepared, &provider.sanitize_rules(), &[]),rewrite 片段硬编码空。sanitize 规则跑了,rewrite 规则一条没跑。这个 bug 静默地把控制台里所有后缀变体方案搞坏:你能正常写 model_pattern = "…-thinking-adaptive-effort-max"path:"thinking" set {display, type} / path:"output_config" set {effort:"max"} / path:"model" set "claude-opus-4-7" 三条规则并保存,但上游收到的 body 没有任何改写。改为传 &provider.rewrite_rules()claude-opus-4-7-thinking-adaptive-effort-max 这类请求的出站 body 现在会正确反映所有匹配的规则。
  • handler 在别名/权限/rewrite 查询前剥掉 body.model 上的 {provider}/ 前缀。 OpenAI 风格客户端习惯把 body.model 写成 "claudecode/claude-opus-4-7-thinking-adaptive-effort-max"。这个带前缀的字符串一路带到 resolve_model_alias、权限检查、ExecuteRequest.model、executor 的 model_pattern 过滤器 —— 而所有存下来的后缀变体规则都是按裸名写的 model_pattern,前缀一加就全不匹配。handler 入口统一剥一次 {provider}/ 前缀,下游所有匹配都看到同一个裸 key。
  • 别名解析不再覆盖 effective_model 之前别名解析会把 effective_model 替换成目标模型的 model_id(比如 claude-opus-4-7-thinking-adaptive-effort-maxclaude-opus-4-7),body 还没到 executor 前 model_pattern 就已经匹配失败了。现在别名只贡献 provider 路由,用户原发的模型名在 effective_model 里一直保留;body 侧把模型名改写成真名这件事交给变体自己的 path:"model" set "<real>" rewrite 规则 —— 在正确的管线位置(协议翻译之后、发送之前)执行。
  • cache_control:空的 system message 和 magic-trigger 清理不再浪费断点。 三个相关修复:(1)flatten_system_text_blocks 会扔掉空 text 块,如果被扔的块此前带着缓存断点,则断点 index 整体向前移一位;(2)magic-string trigger 替...
Read more

v1.0.16

17 Apr 09:23

Choose a tag to compare

v1.0.16

Console polish on the provider config tab: the Upstream Protocol Template row is folded away behind a show/hide toggle, and the hint copy is rewritten to warn against changing built-in channels' routing tables without a reason. Plus a tiny cleanup in the credential-update store path.

English

Changed

  • Upstream Protocol Template collapsed by default. On the provider config tab, the template chips row now sits behind a show/hide toggle and starts collapsed on load / on channel switch. The hint copy is rewritten in a more formal register and explicitly tells readers that built-in channels ship with their own routing tables — pick Custom only when you actually need to customize, and don't change the template unless you know what you're doing. English and 简体中文 strings updated.
  • Credential-update store: drop a redundant into_iter() in the zip. ProviderStore::apply_credential_updates was calling .zip(batch_results.into_iter()) where zip already calls into_iter() on its argument — trimmed to .zip(batch_results). Pure cleanup, no behavior change.

Compatibility

  • Drop-in upgrade from v1.0.15. No DB migration, no HTTP API change, no config change.

简体中文

调整

  • 上游协议模板默认折叠。 Provider 配置页的模板 chips 现在默认折叠,标题旁加了"展开模板 / 收起模板"按钮,加载和切换渠道时都会回到折叠态。提示语改为更正式的措辞,并明确告知:内置渠道已预置路由表,确有自定义需求时才选自定义,如无明确把握请勿修改。中英文文案同步更新。
  • 凭证更新 store 路径的 zip 小清理。 ProviderStore::apply_credential_updates 之前写的是 .zip(batch_results.into_iter()),但 zip 本身就会对实参调 into_iter(),属于冗余。改为 .zip(batch_results),纯清理无行为变更。

兼容性

  • 可直接从 v1.0.15 升级,无需数据库迁移,HTTP API 无变化,配置无变化。

v1.0.15

16 Apr 18:13

Choose a tag to compare

v1.0.15

Fixes a regression in the unscoped proxy path where the providerX/ prefix was stripped from the response's model field — clients that routed via POST /v1/... with "model": "providerX/claude-opus-4-7" saw "model": "claude-opus-4-7" come back. Also rewrites the Quick-Start guide to cover three startup forms (env var / --config flag / default discovery) and point at the suffix-preset alias recipe for forced-thinking variants.

English

Added

  • Quick-Start guide covers three startup forms. Replaces the single env-var launch line with an equivalent --config flag form and a default-discovery form, plus a common-flag reference table. A new closing section points readers at the Models & Aliases guide for creating forced-thinking / effort variants via suffix-preset aliases. Applies to both the English and 简体中文 docs.

Fixed

  • Unscoped proxy preserves the provider/ prefix in the response model field. In proxy_unscoped, the provider/model resolution branch left alias_model_override = None, so ExecuteRequest.response_model_override was never set and the engine left the upstream's raw model name in the response body. Clients that sent "model": "providerX/claude-opus-4-7" now see the same prefixed string echoed back, matching the behavior of the alias-resolution branch on the same handler. Billing is unaffected: build_billing_context falls through to the real model name when the prefixed-name pricing lookup returns nothing.
  • claude_cache_control clippy warnings on Rust 1.95. Two match arms in existing_cache_breakpoint_count triggered the newly-enabled clippy::collapsible_match lint because they wrapped a single if item.contains_key("cache_control") check. Collapsed into match guards (Some(Value::Object(item)) if item.contains_key("cache_control") => …), keeping counting single-expression and aligned with the sibling Value::Array(blocks) => blocks.iter().filter(...).count() arm. No behavior change.

Changed

  • Two transform files' match statements streamlined. Claude → OpenAI Response and OpenAI Chat → Claude response transforms use tighter match expressions (net −7 lines across 2 files). Pure readability follow-up to v1.0.14's guard-clause refactor; no behavior change.

Compatibility

  • Drop-in upgrade from v1.0.14. No DB migration, no HTTP API change, no config change.
  • SDK / protocol consumers: no protocol surface changes.

简体中文

新增

  • Quick-Start 文档新增三种启动方式。 原来只展示 env-var 一种启动命令,现在并列写出 --config 标志式和默认发现式,并附常用标志速查表。末尾新增一节,把读者导向 Models & Aliases 指南,介绍用后缀预设别名创建 forced-thinking / effort 变体的做法。英文和简体中文文档同步更新。

修复

  • unscoped 路由响应体保留 provider/ 前缀。 proxy_unscopedprovider/model 解析分支之前把 alias_model_override 置为 None,导致 ExecuteRequest.response_model_override 没设,引擎也就不会把响应体里的 model 字段改回客户端原来发的带前缀字符串,上游的裸模型名直接透到客户端。现在该分支也把 alias_model_override 填成完整的 providerX/claude-opus-4-7,和同一 handler 上别名分支的行为对齐。计费不受影响:build_billing_context 按带前缀的名查不到价目,会 fallback 到真实模型名,现有价目表按真实模型名 key,一次命中。
  • Rust 1.95 下 claude_cache_control 的 clippy 告警。 existing_cache_breakpoint_count 里两个 match 臂各自嵌了一层 if item.contains_key("cache_control"),触发新启用的 clippy::collapsible_match。改写成 match guard(Some(Value::Object(item)) if item.contains_key("cache_control") => …),计数回归单表达式,和相邻 Value::Array(blocks) => blocks.iter().filter(...).count() 的写法对齐,行为不变。

调整

  • 两个 transform 文件的 match 表达式再精简一轮。 Claude → OpenAI Response 和 OpenAI Chat → Claude 的响应转换用了更紧凑的 match 写法(2 文件净减 7 行)。v1.0.14 guard-clause 重构的纯可读性收尾,无行为变更。

兼容性

  • 从 v1.0.14 直接升级。无 DB 迁移、无 HTTP API 变更、无配置变更。
  • SDK / protocol 调用方:无协议表面变化。

v1.0.14

16 Apr 17:44

Choose a tag to compare

v1.0.14

Console rewrite-rule pipeline is repaired end-to-end: the Set / Remove action tags are now emitted in the snake_case form the backend actually accepts, manually drafted rules no longer disappear on Save (stale-closure race), suffix variants auto-attach a model-rename rewrite so the upstream receives the real model id instead of the alias, and the Claude thinking presets now explicitly set display: "summarized" so the chain-of-thought stays visible in responses. Claude Opus 4.7 pricing is also shipped in the built-in anthropic.json table.

English

Added

  • Claude Opus 4.7 pricing in the built-in anthropic pricing table. sdk/gproxy-channel/src/channels/pricing/anthropic.json now contains a claude-opus-4-7 entry with both default-tier and priority-tier pricing (input $5 / output $25 / cache-read $0.5 / 5m-write $6.25 / 1h-write $10 per 1M default; priority 6× default). New Opus 4.7 providers get accurate billing out of the box — no manual Apply Default Pricing needed.
  • Suffix-variant rewrite now auto-renames body.model to the real model id. addSuffixVariant appends a final { path: "model", action: { type: "set", value: <real_model_id> } } rule after the parameter-setting rules (thinking / reasoning / effort / tier / verbosity). Without this, the outbound request still carried the alias string (e.g. claude-opus-4-7-thinking-high) in body.model and upstream rejected it — alias resolution only rewrote routing metadata, not the body. Ordering matters: the rename is last so the other rules can still match against the alias via model_pattern.
  • Claude thinking presets set display: "summarized" explicitly. -thinking-low / -thinking-medium / -thinking-high / -thinking-adaptive in suffix-presets.ts now pin display so the chain-of-thought stays visible in responses regardless of future default-behavior changes. -thinking-none (disabled) intentionally has no display field (Claude's disabled variant doesn't accept one).

Fixed

  • Console emits snake_case rewrite-action tags. The backend RewriteAction enum uses #[serde(rename_all = "snake_case")] and rejected the capitalized "Set" / "Remove" tags the console had been writing, producing unknown variant 'Set', expected 'set' or 'remove' on every save. The TypeScript RewriteAction type and every writer in ModelsPane / RewriteRuleEditor / RewriteRulesTab / channel-constants now use the lowercase form. normalizeRewriteAction still accepts the legacy capitalized tags on read so already-persisted configs render correctly.
  • Manually drafted rewrite rule no longer vanishes after Save. RewriteRulesTab.save() committed the new draft via setProviderForm, then immediately called the parent's saveProvider, which captured providerForm from its render-time closure — the queued state update had not flushed yet, so the POST body omitted the new rule, and the following reloadAndReselect overwrote local state with the (unchanged) backend version. onSave now accepts an optional rewriteRulesOverride: string, and the draft-commit path hands the freshly-computed JSON to the parent so saveProvider substitutes it into the payload instead of reading the stale closure.

Changed

  • "Channel" form label → "Channel Type" (both locales). The dropdown selects one of ~12 built-in channel kinds (anthropic, claudecode, codex, ...), not a channel instance. The old label read as if it were picking an instance.
  • Transform match statements simplified with guard clauses. Pure readability refactor across 8 response-transform files (Claude → OpenAI / Gemini, Gemini → Claude / OpenAI Response, OpenAI Chat → Claude, OpenAI Response → Claude). No behavior change.

Compatibility

  • Drop-in upgrade from v1.0.13. No DB migration, no HTTP API change, no config change at the surface level.
  • Console rewrite-rule snake_case migration is read-compatible. Any rewrite rules saved with the old capitalized tags still render and match; the next save rewrites them as snake_case. No manual cleanup required.
  • SDK / protocol consumers: no protocol surface changes in this release.

简体中文

新增

  • 内置 anthropic 价目表新增 Claude Opus 4.7 定价。 sdk/gproxy-channel/src/channels/pricing/anthropic.json 新增 claude-opus-4-7 条目,同时包含默认档和 priority 档单价(默认 1M tokens:input $5 / output $25 / cache-read $0.5 / 5m-write $6.25 / 1h-write $10;priority 档 6×)。新建 Opus 4.7 provider 可以直接用内置模板计费,不用手点 Apply Default Pricing
  • 后缀变体的 rewrite 规则现在自动把 body.model 改写回真实模型名。 addSuffixVariant 会在参数规则(thinking / reasoning / effort / tier / verbosity)之后再追加一条 { path: "model", action: { type: "set", value: <真实模型名> } }。之前请求体里的 body.model 仍然是别名(比如 claude-opus-4-7-thinking-high),上游不识别 —— 别名解析只改了路由元数据,没碰 body。改写必须放在最后,否则前面基于 model_pattern 匹配别名的规则会被自己写坏而失配。
  • Claude thinking 预设显式写入 display: "summarized" suffix-presets.ts 里 Claude 的 -thinking-low / -thinking-medium / -thinking-high / -thinking-adaptive 四档现在固定 display: "summarized",确保响应里的思维链始终可见,不依赖 API 默认值将来是否变化。-thinking-none(disabled) 故意不带 display(Claude disabled 分支不接受这个字段)。

修复

  • 控制台写出 snake_case 的 rewrite action tag。 后端 RewriteAction 使用 #[serde(rename_all = "snake_case")],此前 console 写的 "Set" / "Remove" 会直接被拒,保存时报 unknown variant 'Set', expected 'set' or 'remove'。TypeScript 里的 RewriteAction 类型和 ModelsPane / RewriteRuleEditor / RewriteRulesTab / channel-constants 所有写入点统一改为小写;normalizeRewriteAction 在读取路径保留了对历史大写值的兼容,旧配置仍能正常展示。
  • 手动新增的 rewrite rule 保存后不再消失。 RewriteRulesTab.save() 在草稿提交时先调 setProviderForm 写入新规则,然后立刻调用父组件的 saveProvider —— 但 saveProvider 闭包里的 providerForm 是上一次渲染时的值,队列里的 state update 还没刷到闭包,POST 发出的是不含新规则的旧 JSON;接着 reloadAndReselect 又用后端(没保存上的)旧值覆盖本地,新规则就这样蒸发了。onSave 新增可选参数 rewriteRulesOverride: string,草稿提交分支把刚算出的 JSON 直接传给父组件,saveProvider 用它替换 payload 里的 rewrite_rules,不再依赖陈旧闭包。

调整

  • 表单 "Channel" 标签 → "渠道类型" / "Channel Type"(两种语言均改)。 这个下拉选的是 ~12 种内置渠道类型(anthropic / claudecode / codex / ...),不是具体的渠道实例,旧标签读着像在选实例。
  • Transform 中 match 语句用 guard clause 简化。 纯可读性重构,覆盖 8 个响应转换文件(Claude → OpenAI / Gemini、Gemini → Claude / OpenAI Response、OpenAI Chat → Claude、OpenAI Response → Claude),行为不变。

兼容性

  • 从 v1.0.13 直接升级。无 DB 迁移、无 HTTP API 变更、无表面配置变更。
  • Rewrite 规则 snake_case 迁移对读向后兼容。 历史大写 tag 保存的规则仍能正常渲染和匹配;下次保存会以 snake_case 写回。无需手动清理。
  • SDK / protocol 调用方:本版本无协议表面变化。