Releases: LeenHawk/gproxy
v1.0.22
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
vercelchannel for OpenAI Chat Completions, Responses, Models, Embeddings, and Anthropic Messages / Count Tokens, plus console support for Vercel gateway source aliases viaproviderOptions.gateway.only. Vercel's Claude-shaped requests also supportenable_magic_cache,flatten_system_before_cache, andcache_breakpoints. - Kiro / Amazon Q Runtime channel. Added a
kirochannel backed by Kiro IDE 0.12.224'sPOST /generateAssistantResponseSmithy shape. Kiro-specific request conversion and AWS eventstream parsing stay insidekiro.rs; the channel supports non-streaming and streaming text generation through OpenAI Responses / Chat Completions, Claude Messages, and GeminigenerateContent/streamGenerateContent, parses Kiro model-list responses, queries Kiro usage/quota throughgetUsageLimits, 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.1user agent, requests theaicodeOAuth scope, honors configured OAuth authorize/token/userinfo URLs, keeps image-generation / tiered model ids fromfetchAvailableModelsvisible in normalized Gemini model-list responses, avoids forwarding Gemini pagination query params tofetchAvailableModels, 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
accountpayload, so profile switching still extracts the subscribed organization. - ClaudeCode credential cookie input. The admin console now normalizes pasted
Cookie:headers andsessionKey=...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/generationsand/v1/images/editsbodies 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,
globalinference geography, and no emptyserver_tool_useobject. - Vercel credential health on payment failures. Vercel AI Gateway
402 Payment Requiredresponses now invalidate the credential like401/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/ttl1hrender as5m/1hinstead ofauto.
Changed
- ClaudeCode fingerprint editor. The admin console now renders
fingerprintas a localized client-fingerprint editor instead of a raw JSON textarea, with explicit fields for Claude Code andx-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_cache、flatten_system_before_cache、cache_breakpoints设置。 - Kiro / Amazon Q Runtime 渠道. 新增基于 Kiro IDE 0.12.224
POST /generateAssistantResponseSmithy 形状的kiro渠道。Kiro 专有请求转换和 AWS eventstream 解析都收在kiro.rs内,支持通过 OpenAI Responses / Chat Completions、Claude Messages、GeminigenerateContent/streamGenerateContent做非流式与流式文本生成,解析 Kiro 模型列表响应,通过getUsageLimits查询 Kiro usage/quota,并使用本地 token 计数。 - 凭证导入增强. Provider 凭证现在支持按行粘贴 key、JSON object、JSON array 或连续 JSON payload 导入,原始 token 会按渠道自动写入正确的凭证字段。
修复
- Antigravity 渠道刷新. 内置 Antigravity 渠道现在默认使用正式 Cloud Code 端点,发送当前
antigravity/2.0.1User-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 在真实
accountpayload 前返回独立 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/ttl1hcache breakpoint 会显示为5m/1h,不再误显示成auto。
调整
- ClaudeCode 指纹编辑器. 管理控制台现在把
fingerprint渲染成本地化的客户端指纹编辑器,不再只是原始 JSON 文本框;Claude Code 和x-stainless-*请求身份字段都有独立输入项。 - 渠道响应分类. Channel response handling 现在能返回更细的 success/auth/rate-limit/transient/permanent 分类,让 provider 可以按上游特定错误失效或轮换凭证。
- 依赖刷新. 更新 npm 文档 / 工具链依赖,包含 Astro。
staging
Automated staging build from e2406e2701b93a12e24f6a41b10da0fe98efdd07.
v1.0.21
v1.0.21
Protocol packaging is split out, provider/admin behavior is tightened, and several channel compatibility fixes land together.
English
Added
- Standalone
gproxy-protocolrepository 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
fingerprintJSON settings, and normal requests, quota requests, OAuth profile/token exchange, token refresh, and cookie bootstrap all derive their UA from the samefingerprint.cli_version/ user type / entrypoint settings. The old consoleuser_agentdefault 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
/v1to 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 typeduring 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 唯一来源. 控制台现在暴露
fingerprintJSON 配置;普通请求、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
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_research→connector: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?的 blanketFrom<TransformError>推入ExecuteError::bare(meta: None),导致 admin 上游日志显示 500 / 空响应 / 0ms。现在统一通过map_err把UpstreamRequestMeta附到转换失败路径上,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.rs用include_bytes!引用 target/samples/ 里未入库的 HAR 导致新 checkout 编译失败,连同tests/chatgpt_live_e2e.rs(需 live 访问 + access token)一并删除;活跃回归覆盖继续放在 target/scripts/ 本地 Python harness
v1.0.19
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;未知模型回退默认值
- 用
StreamReshaperhook 替代旧实现,并将 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
v1.0.18
Streaming usage 端到端打通(
stream_options.include_usage自动注入 + 所有跨协议流式路径都观察上游 usage),mimalloc 接管全局分配器,缓存流水线重排为 magic → rules → flatten 并用 sanitize 统一清理空块/空消息 + 自动把 cache_control 回迁到最近可缓存块,context-1m-2025-08-07beta 在 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 = trueinjected automatically so the finalusageframe 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_jsonback 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 singlepath:"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
claudecodeversion 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_countfrom/admin/providers/query, butCredentialsPaneonly calledonProviderScopedReloadafter a credential upsert/delete — that refreshed the credential + status rows but left the provider list stale until the next manual reload. Now threadsonReloadProvidersthrough 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_jsonand drops any rule whose source orTransformTodestination 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 withunknown variant 'openai_realtime_websocket', expected one of …on boot. Run-once viaseaql_migrations; safe on fresh DBs. - Empty / whitespace-only content blocks no longer waste cache breakpoints.
finalize_requestnow drops whitespace-onlytextblocks, empty content arrays, and empty messages. When a removed block carriedcache_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_arraysimplified. 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_controlplaced 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-07beta stripped by default on anthropic + claudecode. Anthropic currently rejects the 1M-context beta on these channels;finalize_requeststrips the header before merging operator-suppliedextra_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
--mutedfrom 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_usageinsertion 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-07opt-back-in: if you need the 1M-context beta on an anthropic / claudecode channel, add it explicitly via the provider'sextra_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_websocket、realtime_client_secret_create、realtime_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-07beta. 上游当前在这两个渠道上拒绝 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
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 (somodel_patternnever matched), andbody.model = "provider/variant"from OpenAI-style clients rode theprovider/prefix straight into the filter. All three are fixed — a request toclaudecode/claude-opus-4-7-thinking-adaptive-effort-maxnow actually reaches Anthropic withthinking.display = "summarized",output_config.effort = "max", andmodel = "claude-opus-4-7". The models table is flattened in the same pass:alias_ofis dropped, every model is a standalone row, and the DB migration takes care of existing aliases in place. Plus cache-control gets a newflatten_system_before_cachetoggle, a few breakpoint-shifting bug fixes, and the console's boolean settings get an iOS-style slide switch.
English
Added
flatten_system_before_cachechannel setting (claudecode / anthropic). When the request'ssystemis a list of text blocks, the blocks are concatenated into a singletextblock 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.
StatusToggleis 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 toGlobalSettingsModule's five flags andConfigTab's two cache booleans (enable_magic_cache,flatten_system_before_cache) — the boolean channel settings inConfigTabare now switches instead of afalse/truedropdown. - Migration
m20260417_000001_drop_models_alias_of. Drops thealias_ofcolumn on themodelstable. Runs at most once per DB (tracked inseaql_migrations); a fresh DB skips it because entity sync creates the table without the column in the first place.
Fixed
- Executor actually applies
rewrite_rulesnow.engine.execute/engine.execute_streamwere callingapply_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 authormodel_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 aclaude-opus-4-7-thinking-adaptive-effort-maxrequest now correctly reflects every applicable rule. - Handler strips the
{provider}/prefix frombody.modelbefore alias / permission / rewrite lookups. OpenAI-style clients conventionally sendbody.model = "claudecode/claude-opus-4-7-thinking-adaptive-effort-max". The prefixed string rode straight intoresolve_model_alias, the permission check,ExecuteRequest.model, and ultimately the executor'smodel_patternfilter — 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_modelwith the target model'smodel_id(e.g.claude-opus-4-7-thinking-adaptive-effort-max→claude-opus-4-7) before the body ever reached the executor. That killedmodel_patternmatching 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 ineffective_modelend-to-end. The suffix variant's ownpath:"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_blocksdrops emptytextblocks 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_triggershelper 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
i64trace ID precision.trace_id/downstream_trace_id/cursor_trace_idvalues (and thetrace_idsarray on batch-delete) can exceed 2⁵³, which silently rounds the last digits through JavaScript'sNumber. The console now pre-processes JSON responses to quote those fields as strings beforeJSON.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_ofindirection dropped. Suffix variants used to be model rows carrying analias_ofpointer to the "real" model;resolve_model_aliasfollowed 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 apath:"model" set <real>rule and already stored the rightprovider_id. After this release: every model, suffix-variant or not, is a standalone row;resolve_model_aliasreturns 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 rightprovider_idand variant name. Frontend follows: theonly_aliases/only_realfilter 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_cachelabel 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_updatesdrops a redundant.into_iter()argument tozip, andbatch_upsert_modelssimplifies 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_ofcolumn — and theirprovider_id+model_id = variant-namealready 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/*/queryAPIs, 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_cache、flatten_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-max→claude-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 替...
v1.0.16
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_updateswas calling.zip(batch_results.into_iter())wherezipalready callsinto_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
v1.0.15
Fixes a regression in the unscoped proxy path where the
providerX/prefix was stripped from the response'smodelfield — clients that routed viaPOST /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 /--configflag / 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
--configflag 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. Inproxy_unscoped, theprovider/modelresolution branch leftalias_model_override = None, soExecuteRequest.response_model_overridewas 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_contextfalls through to the real model name when the prefixed-name pricing lookup returns nothing. claude_cache_controlclippy warnings on Rust 1.95. Twomatcharms inexisting_cache_breakpoint_counttriggered the newly-enabledclippy::collapsible_matchlint because they wrapped a singleif 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 siblingValue::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_unscoped里provider/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
v1.0.14
Console rewrite-rule pipeline is repaired end-to-end: the
Set/Removeaction 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 amodel-rename rewrite so the upstream receives the real model id instead of the alias, and the Claude thinking presets now explicitly setdisplay: "summarized"so the chain-of-thought stays visible in responses. Claude Opus 4.7 pricing is also shipped in the built-inanthropic.jsontable.
English
Added
- Claude Opus 4.7 pricing in the built-in anthropic pricing table.
sdk/gproxy-channel/src/channels/pricing/anthropic.jsonnow contains aclaude-opus-4-7entry 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 manualApply Default Pricingneeded. - Suffix-variant rewrite now auto-renames
body.modelto the real model id.addSuffixVariantappends 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) inbody.modeland 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 viamodel_pattern. - Claude thinking presets set
display: "summarized"explicitly.-thinking-low/-thinking-medium/-thinking-high/-thinking-adaptiveinsuffix-presets.tsnow pindisplayso the chain-of-thought stays visible in responses regardless of future default-behavior changes.-thinking-none(disabled) intentionally has nodisplayfield (Claude's disabled variant doesn't accept one).
Fixed
- Console emits snake_case rewrite-action tags. The backend
RewriteActionenum uses#[serde(rename_all = "snake_case")]and rejected the capitalized"Set"/"Remove"tags the console had been writing, producingunknown variant 'Set', expected 'set' or 'remove'on every save. The TypeScriptRewriteActiontype and every writer inModelsPane/RewriteRuleEditor/RewriteRulesTab/channel-constantsnow use the lowercase form.normalizeRewriteActionstill 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 viasetProviderForm, then immediately called the parent'ssaveProvider, which capturedproviderFormfrom its render-time closure — the queued state update had not flushed yet, so the POST body omitted the new rule, and the followingreloadAndReselectoverwrote local state with the (unchanged) backend version.onSavenow accepts an optionalrewriteRulesOverride: string, and the draft-commit path hands the freshly-computed JSON to the parent sosaveProvidersubstitutes 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 调用方:本版本无协议表面变化。