Repository navigation
Integrate official v0.2.15 and simplify OpenAI recovery - #266
Merged
Merged
Conversation
…Responses streams Issue Wei-Shaw#5009 added a failover guard for OpenAI Responses streams that terminate with an empty response.completed (no output, no usage, no error), but the guard is gated on PlatformOpenAI. Grok platform accounts reach the same handler (forwardGrokResponses -> handleStreamingResponseWithReasoning) and exhibit the same upstream silent-refusal shape, so their empty completions are relayed to the client as successful empty turns: Responses SDK clients map the empty completed to finishReason stop and accept the turn with no retry. Extend the guard to PlatformGrok, matching the unconditional guard on the passthrough path (openai_gateway_passthrough.go). Fixes Wei-Shaw#7774
Adds two regression cases mirroring the Wei-Shaw#5009 OpenAI ones for Grok platform accounts (issue Wei-Shaw#7774): - TestOpenAIResponsesEmptyCompletedFailsOverGrok: an empty response.completed on the forwardGrokResponses streaming path must produce UpstreamFailoverError with an empty client body. Verified to FAIL on main without the guard extension and PASS with it. - TestOpenAIResponsesEmptyCompletedWithOutputSucceedsGrok: normal Grok streams with semantic output and usage are untouched. Fixes Wei-Shaw#7774
The Responses WebSocket handler reads the API key auth snapshot once at connect and reuses it for every turn: RecordUsage takes the group pricing from that snapshot, and the profit gate reinstalled in BeforeTurn takes its selling price from the connect-time ctxkey.Group. A group price change therefore never reaches an open connection until the client reconnects, while HTTP requests pick it up once the auth cache entry is invalidated. Each later turn now re-reads the key through APIKeyService.GetByKey (the auth cache the middleware uses) in BeforeTurn. When the key ID, group ID, group platform and subscription type are unchanged, the fresh group is swapped into ctxkey.Group for the turn's profit gate and passed to that turn's RecordUsage. A failed lookup or a key moved to another group keeps the connection snapshot. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chat Completions names a forced function as
{"type":"function","function":{"name":"X"}}, while the Responses API
expects {"type":"function","name":"X"}. ChatCompletionsToResponses passed
the Chat shape through unchanged, so OpenAI API-key accounts on
/v1/chat/completions forwarded the nested shape to /v1/responses and the
upstream rejected the request.
Flatten the named Chat choice; strings and objects already in the
Responses shape are kept as-is.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
chatMessageToResponsesItems only mapped "system" explicitly and sent every other unknown role through the user converter, so Chat Completions developer messages reached the Responses upstream as user turns and lost their instruction priority. The Responses API accepts role "developer" in input messages; convert it like a system message and keep the original role. Downstream converters already understand it (ResponsesToAnthropicRequest folds developer into the system prompt, the Codex transform forwards it unchanged). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Legacy Chat function calling has no call IDs: the assistant turn carries function_call and the role=function result refers to it only by name. ChatCompletionsToResponses ignored the assistant function_call and used the function name as the result's call_id, so the Responses upstream got a function_call_output with no matching function_call and rejected the replayed history. Emit a function_call item for each legacy assistant call and give the following same-name result the same call_id. IDs follow message order (call_legacy_N), so the same history converts to the same input across turns, and skip IDs already used by tool_calls. A result with no preceding call keeps the previous name-based call_id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ic paths The buffered Anthropic aggregators index finalResp.Content with the upstream content_block_delta index after checking only idx < len. A malformed or third-party Anthropic-compatible upstream that sends a negative index makes the request goroutine panic, so the client gets no response and the forward never returns a result to record usage. Add the lower bound in all four buffered aggregators (Chat Completions and Responses, on both the Anthropic gateway and the OpenAI native Anthropic paths); the out-of-range delta is skipped like an index past the end. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Responses refusal arrives as a {"type":"refusal","refusal":...} content
part (streamed as response.refusal.delta), not as output_text. The
Responses → Chat Completions converters only read output_text, and
ResponsesContentPart had no refusal field, so Chat clients received an
empty assistant message when the model refused.
Map refusal parts to choices[0].message.refusal, response.refusal.delta
to delta.refusal, and let BufferedResponseAccumulator keep refusal deltas
so non-streaming replies rebuilt from deltas keep them too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The WS v2 passthrough relay only read output_tokens_details.image_tokens, so image generation over WebSocket billed image input tokens at the text input rate and ignored the hosted response.tool_usage.image_gen breakdown that the HTTP Responses path already merges (extractOpenAIUsageFromJSONBytes + mergeHostedImageGenToolUsage). The relay now reads image input tokens from input_tokens_details or prompt_tokens_details, fills missing image input/output counters from response.tool_usage.image_gen (usage values keep precedence), and carries ImageInputTokens per turn and in the session aggregate into the OpenAIForwardResult used for billing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
渠道定价条目价格留空时按各模型官方默认价回退计费,但向这类条目追加 模型时,前端会用「第一个新增模型」的默认价回填整条价格字段,保存后 条目内所有模型被静默统一成同一个价格,造成少计费或多计费。 自动填充现在只作用于「空条目首次加入单个模型」:条目已有模型时追加、 或一次加入多个模型时都不再改写价格,留空条目继续按各模型默认价回退。 - 新增 PricingEntryCard.modelDefaultPrice.spec.ts 覆盖 4 种场景 - 把该 spec 加入 Makefile 的 FRONTEND_CRITICAL_VITEST,使 CI 覆盖该回归 Closes Wei-Shaw#7796
intersectUpstreamModelMetadata falls back to null for every Codex tool capability field whose value differs across peer accounts. Since e6d191a added service_tiers to codexToolCapabilityFields, a model served by accounts with different (or partially declared) tier lists ends up with "service_tiers": null in the generated Codex manifest. Codex decodes service_tiers as a required array and rejects the whole manifest, so the client loses model metadata for every model. Fall back to [] for conflicting service_tiers (do not advertise any tier that is not shared by all peers), and normalize an explicit null to [] when applying capabilities. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…yte-rate fix(ops): retain byte units for sub-byte throughput
…request-sample fix(channel-monitor): require request samples before health scoring
多协议 API Key 供应商(kimi/zhipu/deepseek/minimax/opencode_go)的默认端点 此前在 account.go 的 GetOpenAIBaseURL / defaultCNProtocolBaseURL / GetAnthropicProtocolBaseURL / GetOpenAIFormatBaseURL 中按平台 switch 重复了 四遍,Responses 能力与 OpenCode 内置分流表也各自散落。 新增 provider_profile.go 作为单一数据来源:每个供应商登记各接入模式的 Chat/Anthropic 默认基址、内置 protocol_rules 与原生 Responses 能力; 上述函数、SupportsNativeCNResponses、IsMultiProtocolAPIKeyProvider 与 defaultOpenCodeProtocolRules 改为查表。纯重构,行为不变:新增测试以旧 switch 逻辑为基准,逐一核对平台 × account_mode × 协议的全部组合。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ProviderEndpoints 由 ChatBaseURL + AnthropicBaseURL 改为以协议为键的 BaseURLs(chat_completions / responses / anthropic),与账号凭证 api_base_urls、前端 defaultCNAdaptiveBaseUrls 的结构一致: - 某协议没有条目即表示不提供该原生端点,SupportsNativeCNResponses 改为 由 responses 条目推导,去掉单独的 NativeResponses 布尔值; - DeepSeek 的 Responses 路径例外(/responses,无 /v1)从 buildOpenAIResponsesURLForPlatform 的平台硬编码移入 profile.ResponsesPath。 运行时行为不变。唯一的函数级差异:智谱 adaptive 账号的 GetCNProtocolBaseURL(responses) 默认值由 CC 基址变为空串;所有运行时调用方 均先经 UsesNativeCNResponses / SupportsNativeCNResponses 守卫,智谱不会走到, TestAdaptiveProtocolBaseURLs 的对应期望随之更新。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
此前 /v1/responses、/v1/chat/completions、/v1/messages 各自用一串 if 决定 上游协议:OpenCode 按模型规则、国产 adaptive 按入站、显式 api_protocol、 Responses 探针四个来源的优先级靠语句先后隐式决定,且每个入口都有 IsOpenCodeGo 特判。 - provider profile 新增 Routing(by_inbound / by_model),OpenCode 登记为 by_model;routesByModel 取代转发路径与 GetAPIProtocol 默认值中的 IsOpenCodeGo 判断。 - 新增 upstream_protocol_routing.go:resolveUpstreamProtocol 以单一函数给出 上游协议(按模型分流 → adaptive 按入站 → 显式 anthropic → CC 直转条件 → Responses),resolveModelRoutedProtocol 以 profile 规则泛化 OpenCode 的规则解析;三个入口改为 switch 该结果选择既有转换路径,Responses 形状 请求体的转换合并为 convertResponsesShapedChatBody。 转换函数本身不变。新增分流矩阵测试经真实入口遍历 平台 × api_protocol × 探针 × 账号类型 × 接入模式 × protocol_rules × 入站 × 模型(2045 组), 与改动前逐条 diff 仅 6 条不同:智谱 adaptive 的非 API Key 账号(UI 无法 创建)在 /v1/responses 入站时由 Responses 改为回落 CC,与 /v1/chat/completions 入口一致;这 6 组前后都在发出上游请求前报错。 协议规则与映射模型相关的类型、函数已被所有按模型分流的供应商共用,同时去掉 OpenCode 前缀(OpenCodeGoProtocolRule → ProtocolRule、matchOpenCodeGoProtocolRules → matchProtocolRules、NormalizeOpenCodeGoProtocolRulesCredentials → NormalizeProtocolRulesCredentials、resolveOpenCodeGoMappedModel → resolveMappedUpstreamModel 等),并删除收敛后已无调用方的 defaultOpenCodeProtocolRules。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
forwardResponsesViaNativeAnthropic 的 defaultMappedModel 是账号 model_mapping 未命中时的兜底模型。此前按模型分流的账号(OpenCode)传空串、其余账号传 reqModel,源自两处分支各自实现。映射未命中且请求模型带首尾空白时,前者的 计费模型名保留空白(上游模型名因 normalizeOpenAIModelForUpstream 已去空白, 两者不一致,定价查找可能落空),后者为去空白的名字。 统一传 reqModel,并移除入口里最后一处 routesByModel 分支。仅影响按模型 分流账号收到带首尾空白模型名的请求:计费模型名改为去空白后的名字;发往 上游的请求不变。新增测试覆盖 OpenCode 与 Kimi 两类账号。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
新增 domain/platforms.go 作为具体平台的单一数据来源:每个平台一条登记, 写明展示名、所走网关(anthropic / openai / gemini / antigravity)、是否国产 单一厂商、定价目录 provider 名,顺序即展示顺序。 以下列表与判断改为查平台清单: - "全部具体平台":用户平台额度白名单、错误透传规则平台列表、组合路由目标 校验、上游计费探测资格、调度快照遍历、组合分组的定价 / 模型映射回退、 组合分组默认模型列表; - "OpenAI 网关族":IsOpenAICompatible、NormalizeOpenAICompatiblePlatform、 Responses 兼容路由判断、count_tokens 分发、组合分组的 OpenAI 文本目标; - 国产厂商判断、渠道定价同步的 provider 映射; - 多协议 API Key 供应商相关的请求头覆盖资格、凭证测试、OpenAI 基址回退改用 IsMultiProtocolAPIKeyProvider; - 分组平台与组合路由目标的请求校验改为自定义校验标签 group_platform / concrete_platform,拒绝规则不变(大小写、首尾空格、别名一律拒绝)。 组合分组的逐平台回退是先命中者生效,CompositePrecedencePlatformIDs 保持 原有顺序 anthropic、gemini、openai,其余按登记顺序追加。依赖具体实现的 能力(OAuth、渠道监控、调度阈值、余额 / 用量窗口、Codex 模型目录等)仍在 各自代码中显式列出。 等价性测试把改动前的每个列表与 switch 原样保留为基准,逐一比较派生结果 (含顺序),谓词覆盖全部平台、composite 与非法值 × 全部账号类型。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
新增迁移 242 删除 user_platform_quotas_platform_check 与 composite_model_routes_target_platform_check(DROP ... IF EXISTS,可重入)。 此后新增平台只需在平台清单中登记,不再需要改约束的迁移;此前 Grok、国产 厂商、MiniMax、OpenCode 共写过 5 次。 平台合法性改由应用层保证,与原约束的拒绝范围相同: - user_platform_quotas 用原生 SQL 写入,不经过 ent Validate,repository 在 BulkInsertInitial / UpsertForUser 写入前校验平台,非法值在发出任何 SQL 前 返回错误(此前由数据库拒绝并回滚); - ent schema 的 platform / target_platform 校验改查平台清单,组合路由新增 target_platform 校验(service 层与 admin 接口的原有校验保留)。 渠道监控的 provider 约束表示已实现的探测能力,不属于平台清单,保留不动。 集成测试(真实 PostgreSQL):在还原旧约束的库上重复执行迁移、约束被移除、 渠道监控约束保留、数据库层可写入未来的新平台值;repository 拒绝未登记平台 且不产生副作用(去掉校验后该测试失败)。全部仓储集成测试通过。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
平台清单之外,后端还有几处用"国产厂商"或"国产厂商 ∪ OpenCode"表示 多协议供应商,新登记的供应商会被漏掉(例如上游模型同步直接报不支持)。 - 适用于全部多协议供应商的判断改用 IsMultiProtocolAPIKey:上游模型同步与 模型目录基址、Anthropic count_tokens 本地估算、HTML 403 豁免与累计计数、Claude 型号 计费候选过滤; - 新增 RoutesProtocolByInbound(profile 分流方式为按入站协议),替换原来 只针对国产厂商、实际描述"按入站协议分流"的判断:Responses 直转回退、 Responses 能力标记(含创建 / 更新后的异步探测调度)、上游计费探测的 adaptive 基址、Anthropic API Key 鉴权方式、OpenAI 输入 token 本地估算。 按模型分流的供应商(OpenCode)仍走 routesByModel 分支。 依赖各家额度 / 余额接口的逻辑(Coding Plan 窗口、余额不足冷却等)仍按平台 显式判断。现有平台上两组判断与改动前逐一相同(测试覆盖全部平台与非法值); 另测试临时登记的新供应商按分流方式分别获得国产厂商与 OpenCode 的行为。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
后端新增 BuildPlatformCatalog:平台清单加上多协议供应商 profile(接入模式、 各协议默认基址、内置分流规则),由测试 TestFrontendBuiltinPlatformCatalogInSync 写成前端内置清单 constants/platformCatalog.builtin.json 并校验一致。前端随后端 一同构建发布,直接使用该清单,取代 credentialsBuilder.ts 中需要手工同步的默认 端点与 OpenCode 分流规则。 改为读取平台清单: - 平台选项 CONCRETE_PLATFORM_OPTIONS / GROUP_PLATFORM_OPTIONS、平台展示名 platformLabel 以及各处 i18n 平台名的默认值; - 渠道定价平台与组合分组平台、用户平台额度、上游模型同步可用平台; - 多协议供应商判断、原生协议能力、各接入模式的默认端点与内置分流规则、 请求头覆写资格; - 系统默认额度与各登录方式默认额度:此前前端只列出 5 个平台(新增国产厂商 与 OpenCode 时漏改),后端一直支持全部平台,现在按清单列出全部平台。 没有专属界面的多协议供应商走通用表单:创建弹窗列出其按钮,接入模式、可选 协议、默认端点与分流规则都来自 profile(按模型分流的供应商显示分流规则编辑 器);编辑弹窗同样适用。未登记专属图标 / 配色的平台使用通用图标与中性配色。 平台按钮分三行:国际平台、国产厂商、多模型聚合平台(OpenCode 与平台清单中 登记的其他多协议供应商)。没有内置模型列表的供应商不预填模型白名单(此前 回落 Claude 模型列表,新账号只接受这些模型),API Key 输入框也不再显示 Claude 的占位符与说明。 AccountPlatform / GroupPlatform 类型放宽为"内置平台 | 任意字符串"。新登记 平台只需重新生成内置清单,无需修改前端代码。 另修正编辑弹窗两处遗漏 MiniMax 的默认端点回退(清空 Base URL 时曾回落到 Anthropic 默认地址)。 测试:credentialsBuilder 以改动前实现为基准,逐一比较全部平台 × 接入模式 × 协议的默认端点与各判断;替换清单后平台选项、展示名、额度列表随之更新;创建 / 编辑弹窗对走通用表单的供应商(按模型 / 按入站两种分流)提交的凭证。更新了 两个固定旧列表写法的测试。平台清单与账号表单的测试加入 CI 前端关键测试列表 (FRONTEND_CRITICAL_VITEST)。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
转发: - 平台清单与 provider profile 新增 command_code:按模型分流,Chat Completions / Responses 基址 https://api.commandcode.ai/provider/v1, Anthropic 基址 https://api.commandcode.ai/provider;内置规则 claude-* → Anthropic、gpt-* → Responses(也支持 Chat Completions)。 - 原生 Anthropic 端点的版本感知拼接改按分流方式判断,转发与连接测试共用 (Anthropic 基址带 /v1 时连接测试不再误报为配置错误)。 按模型的协议集合(模型支持入站协议时直通,免去协议转换): - 分流规则可带协议集合 protocols(首项为首选协议):入站协议在集合中时同 协议直通,否则走首选协议;只有一个协议时与原规则相同,OpenCode 行为不变。 - profile 新增 model_catalog:Command Code 的 /models 为每个模型给出 supported_endpoints。官方默认地址的目录按地址全进程共享,自定义上游按账号 隔离;目录请求的 UA 收敛与账号请求头覆写与转发一致。目录缓存 30 分钟、后台 刷新,失败退避 5 分钟;从未加载成功时首批请求最多等 2 秒,冷启动也按目录 分流。账号规则未命中的模型按目录取协议集合;目录不可用时回落内置规则(账号 未配置规则时)或 Chat Completions。 - 三个入站入口共用的 resolveUpstreamProtocol 增加目录参数。 - 前端分流规则编辑器可为每条规则勾选"也支持"的协议;提供模型目录的平台, 兜底行改为说明按上游模型列表选协议。 连接测试: - 按模型分流的平台共用一条测试路径(协议与网关同一判定,含模型目录;默认 测试模型取自 profile),不再落入 Claude 测试路径。 - 首个分支由"国产厂商"改为"按入站协议分流";adaptive 测试跳过 profile 未 提供的 Anthropic 端点。现有国产厂商行为不变。 - 连接测试是 OpenCode 专属分流入口的最后一个调用方,改走统一判定后删除 ResolveOpenCodeGoUpstreamProtocol、openCodeGoNativeProtocol,以及此前就只剩 测试使用的 OpenCodeGoModelProtocol;路由矩阵的旧行为基准改为测试内独立复述。 额度与余额(/alpha/whoami、billing/credits、billing/subscriptions、 usage/summary): - 额度探测写入 5 小时 / 每周窗口(限额套餐)与还原出的月度窗口,同时写入 积分余额;余额探测只取积分。仅对官方主机上的 API Key 账号生效。 - 订阅周期或本周期用量取数失败时保留上一次的月度快照,不当作没有月度窗口 清掉;窗口尚未开始(没有重置时间)时清掉上一个窗口的重置时间。 - whoami 取不到时探测整体失败,不按个人账户继续(组织账号会查到成员的个人 钱包,并据此按余额停调)。 - 阈值停调与定时检测纳入 Command Code;有充值积分时上游跳过窗口检查,窗口 快照不参与停调与冷却;积分低于余额阈值时临时停调。 - 上游计费探测的官方域名加入 commandcode.ai,不把 Key 发往官方主机上并不 存在的中转计费接口。 上游错误(依据 commandcode.ai/docs/troubleshooting/errors,按文案分类, 402 / 403 / 429 同样处理): - 5 小时 / 每周窗口用满:带原因的临时停调,到文案中的 "Resets in …",解析 不出时回落额度快照;充值积分不受窗口限制,额度 / 余额探测发现充值积分后 只解除这一类停调。 - 积分耗尽(含 usage_exceeded):可恢复的临时停调,积分恢复后由周期检测 解除,不再永久置为 error。 - 组织花费上限:文案指明模型("set for <模型>")且请求模型已知时只写模型级 限流;成员总额度或作用域不明时整个账号冷却,最长一小时。 - 普通频率限制走默认 429 逻辑,不再冷却到窗口重置点。 前端: - 账号列表显示额度窗口与积分余额,阈值设置增加 command_code。单元格可见性 改为按账号判定,与后端一致:只对官方主机上的 API Key 账号显示,自定义中转 显示占位符,不再每次打开列表都探测出一行报错。 - 使用官网的官方标志(圆角方块内镂空 ⌘);配色为中性灰(品牌黑色已由 Grok 使用)。 测试基准中原先用作"仅服务端登记"示例的 command_code 改为虚构的 acme_router; 新增的前端测试加入 CI 前端关键测试列表。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cline API(https://api.cline.bot/api/v1)是 OpenAI 兼容的多模型聚合端点, 只提供 Chat Completions(Cline 自己的客户端同样只走该端点),模型名带厂商 前缀。同一个 API Key 下有两个互不影响的额度来源,由模型名决定扣哪一边: cline-pass/* 走 ClinePass 订阅(5 小时 / 7 天 / 30 天滚动上限),其余付费 模型扣账户积分;cline-free/* 免费模型只有逐模型的每日额度。 转发: - 平台清单与 provider profile 新增 cline:按入站协议分流,只登记 Chat Completions 端点,Responses / Anthropic 入站由现有转换链转为 Chat Completions,无需新增转发代码。 - 只有一个接入模式,不需要选择账号类型。 - 连接测试未指定模型时使用 profile 默认模型(固定 Chat Completions 的账号 此前落到不带厂商前缀的通用默认模型);订阅了 ClinePass 的账号改用订阅 模型,不消耗积分,ClinePass 冷却中时仍用按量模型。 用量与余额:API Key 调 /api/v1/users/me/plan/usage-limits(三档窗口的已用 百分比与重置时间,未订阅时 404)与 /api/v1/users/me、/users/{id}/balance (余额单位为百万分之一积分,1 积分 = 1 美元),兼容 {success, data} 信封, 只查官方主机。复用额度探测与周期检测:账号列表显示 ClinePass 窗口与积分 余额;窗口用满时 ClinePass 模型冷却到重置时间,未订阅时不调度 ClinePass 模型,积分低于阈值时冷却付费模型;数据显示恢复后自动解除,但只解除探测能 证明已恢复的原因(窗口用满、未订阅、积分不足),组织账户、所需订阅档位、推理 额度与花费上限的冷却到期后由请求重新确认。周期检测中走账号接口探测的平台 改为登记表(平台、支持判定、检测函数一一对应),按账号所属平台分派。 上游错误(依据 docs.cline.bot/api/errors 与 Cline 客户端的错误分类,按文案 识别):积分不足(含其他 402)、组织花费上限、推理额度上限、ClinePass 超限、 未订阅 ClinePass / 组织账户、免费模型每日额度。两边的超限只冷却请求模型所属 的一边(模型级冷却键 cline:pass / cline:credits,调度按请求模型检查),不停 整个账号;免费模型只限该模型,冷却到文案中的 "try again in …"。ClinePass 超限冷却到快照中对应窗口的重置时间,没有快照时 5 小时窗口 1 小时、7 天 6 小时、30 天 24 小时。普通频率限制走默认 429 逻辑。402 的冷却写入失败时 也不落入默认分支永久置 error(探测只覆盖激活账号,置 error 后无法自动恢复)。 余额类冷却时长抽为 cnBalanceCheckCooldown 共用。 上游计费探测的官方域名加入 cline.bot。 前端:官方标志(机器人头像)、violet 配色(品牌紫)、复用额度与余额单元格 (同样只对官方主机上的 API Key 账号显示);接入模式展示名抽为共用函数,编辑 弹窗不再显示原始模式值。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
feat(platform): 平台与多协议供应商改为数据驱动,并接入 Command Code 与 Cline
…_call ChatGPT's Codex endpoint now rejects requests whose input replays a hosted web_search_call item unless tools declares web_search, failing the stream with "response protection is unavailable". Codex local context compaction sends the full history with tools:[], so every compaction after a web search fails and the session gets stuck in a reconnect loop. For OAuth transform, passthrough and WebSocket paths, append a cached-only web_search tool when the history contains web_search_call and no web_search tool is declared. When the caller offered no tools, pin tool_choice to "none" so the injected tool cannot be invoked. The /responses/compact wire shape is left untouched. Fixes Wei-Shaw#7927
Responses Lite rejects hosted tools at the top level ("responses Lite does
not support top-level tool type web_search"), so Lite requests now carry the
injected web_search tool in an input additional_tools item: extend the
caller's first additional_tools item, or insert one before a trailing
compaction_trigger so the v2 compaction wire keeps the trigger last.
The HTTP passthrough path also runs the shared compatibility normalizer on
/responses/compact; thread the compact flag through so that endpoint is
left untouched, and drop the now-redundant call from the passthrough OAuth
body normalizer.
…web-search-history-tool fix(openai): declare web_search when OAuth history replays web_search_call
added 2 commits
October 9, 2026 22:07
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Integrate official Sub2API v0.2.15 (f2669c8) over the admitted v0.2.14 downstream, including Cline/Command Code, catalog-driven platforms, protocol and model-discovery fixes, TPS and UI request-lifetime fixes. OpenAI encrypted-content recovery now follows official HTTP/WS and ordinary failover behavior; retire the former downstream state/repair/failover modules and admin API/page while retaining stored settings and diagnostic records.
Keep Codex identity/borrowing, Pelican observation, system prompts, capacity evidence, administrator visibility and Claude recovery. Preserve namespaces for named standalone API-key tool outputs with official lazy reconstruction. Compact account filters retain existing facets and selections; new platforms expose prompt/effort extensions only on supported paths.
Official 242 is followed by additive 277 because immutable downstream 251/260/265 restore the quota CHECK on fresh installations. An isolated PostgreSQL 18.1 run verified the effective historical sequence, repeated execution, original row preservation and Cline/Command Code inserts. No historical SQL checksum is rewritten.
Validation: focused fake-upstream HTTP/WS recovery, namespace, prompt/effort, mapped-model and WS pricing regressions passed; filter disclosure and the corrected reactive platform ID catalog passed. Vue typecheck, focused ESLint and source compilation passed. Required PR CI remains authoritative. No real model requests were sent.