Repository navigation
feat: integrate v0.2.9 and fix authoritative model context capacity - #212
Merged
Merged
Conversation
…ery instead of hiding mapped models A single passthrough account made GetAvailableModels return nil for the whole group, so every other account's model_mapping was dropped from /v1/models and the Codex catalog. Treat passthrough accounts like unmapped ones: skip their (possibly stale) mapping and let supplementUnmappedOpenAIModels add the default set, while ordinary accounts' mappings still reach the list. Refs Wei-Shaw#6647, Wei-Shaw#7517
Wei-Shaw#7395 made Codex (and Grok) imports store a base URL ending in /v1, but the usage script still appends a hard-coded /v1/usage, so CC Switch requests /v1/v1/usage, gets a 404 and shows "query failed" for every newly imported Codex/Grok provider. Move the script into ccswitchImport.ts and strip an existing trailing /v1 from {{baseUrl}} before appending /v1/usage, which covers both the imported value and base URLs users edit either way later.
…tion OpenAI candidate filtering reads the Redis metadata projection, but filterSchedulerExtra dropped auto_reset_credit_enabled, the 5h/7d reset-credit thresholds and codex_auto_reset_credit_state. The scheduler therefore always saw automatic reset credits as disabled, so accounts were paused at the ops quota auto-pause threshold even when a fresh state showed an available reset credit. The "keep scheduling until the reset-credit threshold" branch never took effect, and accounts with credits stayed idle until their window reset naturally. - Keep the four keys in the scheduler projection; the test round-trips the real JSON payload and resolves the credit config from it. - Once visible, every scheduling pass notifies the auto-reset worker for paused credit-enabled accounts, and each notification reloads the account. Add a 30s per-account cooldown for the scheduler hot path only; other event-driven notifications are unchanged and the per-minute scan remains the fallback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pstream - OpenCode Zen / Go 把 deepseek-* 模型转发给 DeepSeek,thinking mode 的 reasoning_content 约束原样生效,上游 400 原文一字不差地回吐 - 原判定只认 platform=deepseek 与 base_url 指向 api.deepseek.com, opencode_go 账号漏出,Responses→CC 回退在缓存未命中时必踩 400 - 按「官方 OpenCode 上游 + deepseek-* 模型」补一条判定,不放宽成任意上游的 deepseek-* 模型名,避免对无此约束的上游无谓改写请求体 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…odel isReasoningModel matched the literal "gpt-5" prefix plus the GPT-6 Sol/Luna spellings, so gpt-6 and gpt-6-astra (both already in the model catalog and price list) fell into the sampling branch. Anthropic Messages and Chat Completions requests converted to the Responses API then forwarded temperature/top_p, which the Responses API rejects for these models with "Unsupported parameter". Key the check on the parsed GPT generation number instead, keeping the existing Sol/Luna spelling match, so later families are covered without another edit. Non-generation GPT families (gpt-image-1, gpt-audio) and gpt-4.x are unaffected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s empty BufferedResponseAccumulator.SupplementResponseOutput rebuilt the output only when the terminal response had an empty output array. Upstreams can also end with a non-empty output whose message carries no (or only blank) output_text. The buffered Chat Completions and Anthropic Messages paths then returned an empty reply although the text had streamed, while usage still billed the terminal output_tokens. When the terminal output has no usable message text, fill the first empty output_text part (or append one, or append a message item) from the accumulated deltas. Non-empty terminal text stays authoritative, and nothing is synthesized when no text streamed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The canonical Anthropic stream leaves tool_use input empty on
content_block_start and streams the arguments as input_json_delta.
Anthropic-compatible relays may instead put the complete arguments on
content_block_start and send no delta. The Anthropic-to-Responses stream
converter ignored that input, so function_call_arguments.done carried ""
and the closed item "{}", and clients executed the tool with no arguments.
Keep the inline input as a seed. A real input_json_delta supersedes it, so
canonical streams keep their exact event sequence and two JSON documents are
never concatenated. When no delta arrived by content_block_stop, emit the
seed as a single arguments delta before the done event, which still repeats
exactly what the deltas streamed. Empty, "{}" and null inputs keep the
existing "{}" fallback.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hem unset When a channel pricing entry left image_output_price empty, GetModelPricingWithChannel and the pricing resolver zeroed the image output price and marked it explicit, so image output tokens were billed at $0. image_input_price followed the same "unset means zero" rule and fell back to the text input price instead of the catalog image input price. A channel that lists an image model such as gpt-image-2 in token mode without filling in prices therefore generated images without charging for image output tokens, while the available-channels view (Wei-Shaw#2475) displayed the catalog image price for the same entry. Wei-Shaw#2930 wanted an explicit 0 on the channel to stop falling back to the catalog; the change applied the same treatment to unset values as well. Treat the two image fields like every other token price field: - Set on the channel (including 0): override the catalog. An explicit image_output_price keeps ImageOutputPriceExplicit, so 0 stays free. - Left empty: keep the catalog price (LiteLLM or built-in fallback). If the catalog has none, computeTokenBreakdown still falls back to the text input/output price. The admin UI saves an empty field as null and only an entered 0 as 0, so the two cases stay distinguishable. The flat, interval and GetModelPricingWithChannel paths now share applyChannelImagePriceOverrides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…issing The API-key Responses capability probe treated every 404 as conclusive and stored responses_supported=false. The probe model is the first mapped upstream model in lexical order, so on third-party accounts it is often an auxiliary entry such as codex-auto-review; a model_not_found answer then permanently routed the account away from /v1/responses although the endpoint works. A 400/404 whose error code/type or message says the probe model does not exist or is unavailable is now inconclusive, so the stored capability is not overwritten. Plain 404/405 still mean the endpoint is missing. The probe also prefers a general gpt-* text model (not an image model) among the mapped models before falling back to the first one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…search fallback The personal-access-token /v1/alpha/search fallback turned any upstream Responses SSE body into a 200 search result and billed one web search call. Error, response.failed and response.incomplete events, a response.completed with a non-success status or without its response, a truncated stream and a bare [DONE] were all accepted, returning partial text as a successful and billable search. Parse the stream strictly: those shapes now return an error, so nothing is written to the client and no WebSearchCalls result is produced. A successful response.completed keeps the existing output and citation handling. The existing PAT metadata test now feeds a Responses SSE stream, which is what that upstream path returns. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chat Completions file parts already become Responses input_file, but the Antigravity path dropped them when converting to Anthropic and then to Gemini. Map data-URI input_file to a document block and emit it as inlineData so Gemini receives the PDF. Fixes Wei-Shaw#7583
…ck off after query failures With the credit config now visible to the scheduler, every scheduling pass notifies the auto-reset worker for paused credit-enabled accounts. evaluateAccount forced an upstream query whenever the reset threshold was reached, regardless of the last result. Accounts with no credits left and 7d >= 95% were therefore polled on /wham/usage every ~15-20s across instances (previously once a minute by the scanner), and during upstream outages the failed state caused the same storm. - At the reset threshold, skip the forced query while a no_credit result is still within the state TTL (10 min); re-query once it expires so newly granted credits are still picked up. - After a query-stage failure (RESET_CREDIT_QUERY_FAILED, USAGE_SNAPSHOT_WRITE_FAILED, RESET_CREDIT_DETAILS_UNAVAILABLE), wait one minute before querying again, including snapshot-staleness triggers. - Redemption-stage failures are unaffected and still retry immediately with the same idempotency key; accounts with available credits still query and redeem immediately. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…LFORMED_FUNCTION_CALL
客户端在响应提交前断开时,只有排队/换号阶段和 OpenAI 的兜底写入会标 499。 Claude 非流式与 Gemini 的 Chat Completions / Messages / Responses 兼容入口 在等待上游时断开,由 GatewayHandler.ensureForwardErrorResponse 补写 502; Gemini 原生入口什么都不写,落成 200 并被 ops 记成一条 provider 的 "Recovered upstream error";Antigravity 回写 502。这些行都按上游失败计入 SLA 与上游错误数。 - GatewayHandler.ensureForwardErrorResponse 补客户端断开检查,与 OpenAI 版一致 - GatewayHandler 的 Messages / ChatCompletions / Responses 与 Gemini 原生入口: 首次选号失败时先判断客户端断开;ChatCompletions / Responses 循环开头改用 failoverClientGone,不再直接 return 落成 200 - Gemini 原生入口:forward 失败时补 499 标记;并发槽错误改走 concurrencyErrorResponse 统一映射(断开 499、排队满/超时 429、其余 503) - Antigravity 上游响应前断开回写 499;googleapi 与 Antigravity 的 Google 错误 格式把 499 映射为 CANCELLED - OpenAI alpha search 非 failover 错误分支补断开检查 - Claude / Gemini / OpenAI 传输层错误:请求 context 已取消时不记 ops 上游事件 - ops:IgnoreContextCanceled 开启时跳过没有上游错误上下文的 499;带上游错误的 499(上游失败后客户端没等到换号结果就离开)仍按上游失败落库 计费不变:Gemini 流式中途断开的用量处理不在本次范围。新增 handler/service 单测覆盖各入口的断开场景与 ops 过滤规则。
参数逐项传递,不再经 sh 拼接,避免密码含 shell 特殊字符时被展开或截断; 空密码时按 redis 语义不设密码。
… time UsageProgressBar returned 'now' whenever showNowWhenIdle was set and utilization was 0%, ignoring resetsAt. OpenAI Codex 7d windows at 0% usage still carry a future reset time, so the admin account list hid it. Only fall back to 'now' when no reset time is known.
RecordUsage treats a missing price as zero cost on the first pass, but the Free Fast Standard re-evaluation returned the same pricing error. Requests in a free_openai_fast group sent at priority/fast tier to a model without pricing therefore lost their usage log entirely. Ignore pricing-unavailable errors on the Standard pass and keep the zero-cost entry, matching the first pass. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…df-inline-data fix(antigravity): forward chat PDF file parts as Gemini inlineData
…put-on-block-start fix(apicompat): keep tool arguments sent on content_block_start
…-empty-final-text fix(apicompat): recover streamed text when the final output message is empty
…asoning-models fix(apicompat): treat every GPT generation from 5 on as a reasoning model
…issing-pricing fix(billing): keep zero-cost usage log when Free Fast has no pricing
…-alias-main fix: recognize OpenRouter Claude Opus 5.5 alias for billing
…ch-require-completion fix(openai): require a successful completion before billing an alpha search fallback
…l-unavailable-inconclusive fix(openai): keep Responses support unknown when the probe model is missing
…uota-reset fix(openai): retain quota pause until known future reset
…-context-billing fix(billing): 账号统计成本按 OpenAI 账号开关计入长上下文价
fix(model-plaza): apply independent video billing multipliers
…st-glob feat(groups): support wildcards anywhere in model allowlists
…image-price-inherit-when-unset fix(billing): keep catalog image prices when channel pricing leaves them unset
…-form fix(deploy): redis 启动命令改用 exec 列表,修复密码含 shell 特殊字符时失效
fix(gateway): 客户端断开统一标记 499,不再被记成 502/200 上游错误
…-rollover-upstream fix(openai): break websocket chain on context rollover
…uto-reset-credit-sched-projection fix(scheduler): keep auto reset-credit fields in the scheduler projection
…tream fix(openai): preserve caller beta headers for HTTP Responses
…el-discovery-merge fix(gateway): let OpenAI passthrough accounts supplement model discovery instead of hiding mapped models
…zen-deepseek-reasoning-placeholder fix(openai): inject DeepSeek reasoning placeholder for OpenCode Zen upstream
…alformed-function-call-retry fix(antigravity): trigger failover retry on empty stream caused by MALFORMED_FUNCTION_CALL
…disabled-openai fix(openai): honor disabled thinking in Claude Messages bridge
…ured-output-beta fix(anthropic): preserve requested structured outputs beta
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.9 (
4c00df2e0183e2c70b7fa8ba45914205e36aad0c) and correct the model-capacity data flow. GPT API/OAuth and relay accounts previously inherited Codex subscription defaults; the shared resolver now prefers the applicable official API specification and its explicit maximum, while keeping administrator overrides highest.Validation: incremental focused capacity/projection/CAS/protocol and frontend fixtures; normal required CI runs on this PR. Details and source pins are in
.downstream/upstream-review-v0.2.9.mdand.downstream/upstream-risk.json.Release target:
v0.2.9-codexrip.1; fixed downstream image, US origindeploy-preserve, resources/runtime preserved, only Sub2API recreated.