5501 Commits
Author SHA1 Message Date
Wesley Liddick f25f399be0 Merge pull request #5905 from wucm667/fix/issue-5883-restore-custom-tool-alias
fix(openai): restore namespaced custom tool aliases
2026-08-24 11:23:37 +08:00
Wesley Liddick 748b84a15a Merge pull request #6081 from wucm667/fix/issue-5942-deferred-tools
fix(responses): remove orphan deferred tool flags
2026-08-24 11:23:25 +08:00
Wesley Liddick fa42c3d706 Merge pull request #6080 from alfadb/fix/cc-stream-empty-tool-call-identity
fix(openai): 剔除流式 tool_call 后续 delta 中的空 id/name
2026-08-24 11:23:12 +08:00
Wesley Liddick fb01f5df2c Merge pull request #6060 from anguobao123/codex/document-openai-force-http-fallback
fix(deploy): forward documented Gateway settings
2026-08-24 11:22:38 +08:00
Wesley Liddick 8238956799 Merge pull request #6095 from xiaxiaxaia/fix/openai-oauth-upstream-model-sync
fix(openai): sync models for OAuth accounts
2026-08-24 11:21:58 +08:00
Wesley Liddick e00a8abdd5 Merge pull request #6124 from anguobao123/codex/diagnose-openai-load-batch-exclusions
fix(scheduler): diagnose load-batch OpenAI exclusions
2026-08-24 11:21:30 +08:00
Wesley Liddick a52665d079 Merge pull request #6061 from shunwang-crypto/fix/ops-mixing-cgroup-host-memory
fix(ops): avoid mixing cgroup and host memory metrics
2026-08-24 11:20:51 +08:00
feeeei b07d85c497 模型广场:分时计价同步渠道仅工作日规则
- 阶梯表分时倍率透传渠道 weekdays_only;探针锚点显式固定在工作日
  (原 2026-01-01 恰为周四是巧合,锚点落周末会把仅工作日时段整组剔除)
- 前端时段徽章加「工作日」前缀,tooltip 说明周末全天按标准价计费
2026-08-24 11:16:00 +08:00
wucm667 bc4a9ae432 fix: prevent duplicate Anthropic cache TTL billing 2026-08-24 11:05:57 +08:00
alfadb cc894ef578 fix(openai): strip empty streamed tool-call id/name
DashScope/DeepSeek later tool_call deltas send empty id and
function.name. Clients that merge with !== undefined overwrite
the first delta's identity and dispatch unknown tool "". Drop
those empty fields on the raw Chat Completions SSE path.
2026-08-24 10:59:52 +08:00
feeeei 83d4eb6a43 模型广场:增加渠道分时段计价展示
- 阶梯表查询附带分时倍率时段:时段取自计费解析到的渠道定价,
  每个时段的倍率由计费的 resolvedChannelTimeMultiplier 在时段内取值,
  分组价卡覆盖或配置非法时自然不出现;倍率为 1 的时段不列
- 广场模型条目新增 time_pricing(时区 + 时段 + 倍率)
- 前端把分时时段展开为独立行:模型名旁标注时段,价格按时段倍率折算,
  倍率列显示生效倍率;时区与计算口径放在提示中
2026-08-24 10:50:52 +08:00
feeeei ecce0769c0 模型广场:上下文档位统一标签形态并保证升序
- 阶梯表标签由计费层统一生成:有上限的档为「≤上限」、末档为「>下限」
  (达到阈值即进高档时用 < / ≥),不再沿用渠道区间的自定义 tier_label;
  合并同价段只看单价
- 前端档位按下限升序兜底展示,无标签时按同一形态生成
2026-08-24 10:50:52 +08:00
feeeei 377d1230fc 模型广场:按计费阶梯单价表展示长上下文档位
- 新建 ModelPlazaService(持计费服务与定价解析器)承接广场聚合,
  token 模型的单价与档位全部取自 ResolveContextPricingSchedule,
  渠道选择与计费同源;图片/按次模型沿用原档位合成
- 官方参考价改走计费目录(LiteLLM → 内置兜底 → 模型策略),带官方阶梯
- DTO 增加 long_context_pricing_enabled / long_context_basis /
  official_pricing.intervals
- 前端实付与官方三列按档分行(标签只在首列,其余列按行对齐),
  缓存列按档展示写/读价,边际计价以徽章与 tooltip 标注,
  分组关闭阶梯时在头部说明
2026-08-24 10:50:52 +08:00
feeeei 6466978d2f 计费:统一 token 计费路径选择并提供上下文阶梯单价表查询
- BillingService.CalculateTokenCostForRequest 承接网关的路径选择
  (分组/渠道定价 → 平台旧长上下文规则 → 内置目录),网关改为调用该入口
- Gemini /v1beta 的 200K 边际翻倍常量从 handler 移入
  BillingService.LegacyLongContextRule,入口只声明适用
- 新增 ResolveContextPricingSchedule:沿用 Resolve 解析链收集断点
  (渠道区间边界、目录阶梯阈值、旧规则阈值),每档单价由真实计费函数
  探针差商得出,倍率/策略变更无需同步;附阶梯表 vs 计费函数的对账测试
2026-08-24 10:50:52 +08:00
Wesley Liddick 3b8a148bcf Merge pull request #6111 from feeeei/fix/request_billing
fix(billing): bill fast mode by the tier upstream actually served
2026-08-24 10:43:17 +08:00
Wesley Liddick 3e45d4e030 Merge pull request #6089 from lyen1688/feat/channel-time-pricing-weekdays
新增渠道时间段定价工作日生效规则
2026-08-24 10:21:47 +08:00
shaw 40aaf7b3ae fix: handle plugin route health update errors 2026-08-24 10:02:06 +08:00
shaw 684d9efb1f fix: harden plugin runtime and UI bridge 2026-08-24 09:50:46 +08:00
shaw 26ac0498f2 test: update plugin management settings contract 2026-08-24 09:16:16 +08:00
shaw 40ea3aebad feat: add OAuth outbound transport plugin system 2026-08-24 09:03:37 +08:00
anguobao123 3fd66a33be fix(scheduler): diagnose load-batch OpenAI exclusions 2026-08-24 01:25:54 +08:00
akihitohyhandClaude Opus 5 243921dc0a fix(openai): rebuild streaming terminal output from the reported items
A terminal event that arrives with an empty output was rebuilt from delta
accumulation. BufferedResponseAccumulator models only one reasoning item, one
message, and N function calls, and records no item id, status, or phase, so a
turn carrying several items collapsed into a single fabricated message: the
reasoning item disappeared, the real message id was replaced, and phase was
lost.

reconstructResponseOutputFromSSE already prefers the raw output_item.done
items over accumulation for buffered responses. The streaming path had no
equivalent because it never sees the whole body at once. Collect the raw item
of each output_item.done keyed by output_index and rebuild from those, falling
back to accumulation only when the stream reported no done item at all.

Items are stored as raw JSON, so vendor extensions and item types this gateway
does not model survive the rebuild verbatim.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 20:49:36 +08:00
wucm667 19da0f240e fix(gemini): sanitize unsupported tool schema fields 2026-08-23 18:38:11 +08:00
feeeei 75faedda95 计费:fast/priority 按上游响应实际档位只降不升计费
此前 OpenAI service_tier 与 Anthropic speed 的计费档位只看请求侧,上游
因容量把 priority/fast 静默降为 default/standard 时仍按 2x 收费。现在:

- upstreamResponseModelObserver 同时观察响应侧档位:OpenAI 只信终止事件
  与无类型 body 里的 service_tier(response.created 为请求回显,忽略),
  Anthropic 读 usage.speed;查找仅在带 model 的帧上触发
- ResolveBillingServiceTier 只降不升:响应档位比请求便宜才采纳,更贵、
  未知或缺失一律沿用请求侧,与图片尺寸归并、response_model 计费的
  "不得更贵"不变式一致
- usage_logs.service_tier 记录实际计费档位,降级写
  billing.service_tier_downgraded 审计日志;HTTP、WS 及 ws_v2 relay 全覆盖
2026-08-23 16:53:28 +08:00
Long Li fc589bce17 fix(codex): address routed catalog review feedback 2026-08-23 15:43:57 +09:00
wucm667 4eadee1074 [verified] test(openai): update responses bridge signature 2026-08-23 08:45:04 +08:00
wucm667 31d5b67baa fix(openai): restore namespaced custom tool aliases 2026-08-23 08:11:20 +08:00
jjaw 49752060fc fix(monitor-v2): resolve composite group error facts to concrete account platform
Composite groups are a routing layer. The usage-side aggregation already
maps their traffic to the concrete account platform via
usageLogEffectivePlatformExpr, but the error aggregation read
ops_error_logs.platform verbatim. Pre-routing failures on composite groups
fall back to the group platform 'composite', which is never an enabled
monitor v2 config platform, so those error facts were filtered out of
every channel monitor v2 query and composite groups looked permanently
healthy.

Join groups/accounts in the error dedup CTE and resolve the effective
platform the same way as the usage side: account platform first, then a
real recorded platform, else 'unknown'. The window delete+rewrite
recompute rewrites historical facts with the corrected key.
2026-08-23 02:33:09 +08:00
xiaxiaxaia 913ec5d74b fix(openai): sync models for OAuth accounts 2026-08-23 02:07:59 +08:00
William Drake a6b11ccced fix(openai): honor OpenCode Go usage reset durations
Recognize GoUsageLimitError responses and parse both single and composite reset durations from their human-readable messages. Keep API-key accounts rate-limited until the parsed reset instead of falling back to the short default cooldown.
2026-08-22 10:26:56 -07:00
lyen1688 77e0409f7c 新增渠道时间段定价工作日规则 2026-08-23 00:30:27 +08:00
wucm667 7498d8fdc8 fix(openai): enforce serial tool calls for Responses Lite 2026-08-22 19:40:19 +08:00
shunwang-cryptoandClaude Opus 4.8 cd05772e91 fix(ops): avoid mixing cgroup and host memory metrics
In Docker + cgroup v2 with no memory limit set, /sys/fs/cgroup/memory.current
returns a small container number while /sys/fs/cgroup/memory.max is "max".
readCgroupMemoryBytes then returned (used=<container>, total=0, ok=true).

collectSystemStats used that container "used" but, being unable to derive a
cgroup total, filled the total from the host via gopsutil. The dashboard then
computed container_used / host_total, e.g. ~60MB / 23GB ≈ 0.3% — wildly
understating real usage.

Fix: introduce resolveMemoryStats, which picks a single self-consistent
(used, total, percent) trio from ONE source. cgroup metrics are used only when
the cgroup exposes both a current usage AND a concrete limit (memory.max != max,
so total > 0); otherwise used/total/percent all fall back to the host reading.
The two sources are never mixed.

- memory.current valid + memory.max = "max"  -> all host metrics
- memory.current = 512MiB + memory.max = 2GiB -> ~25% from cgroup
- no cgroup (bare metal)                       -> all host metrics

CPU metric behavior is unchanged (cgroup attempt then host fallback).

Adds ops_metrics_collector_memory_test.go covering all branches.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-22 19:35:31 +08:00
wucm667 7a09a2eaf7 fix(responses): remove orphan deferred tool flags 2026-08-22 16:42:56 +08:00
Jarl d493ce0bb2 fix(openai): scope codex identity to oauth account 2026-08-22 16:06:04 +08:00
Yoga Sakti e0e5e45cd2 fix(openai): keep restored tool-call item IDs typed
The Responses client-tool restore raised an upstream function_call back to
custom_tool_call and tool_search_call without touching its item ID, so the
client received a custom_tool_call carrying the upstream's fc_ ID. That
combination is invalid: once the item lands in the client's history, any
later replay to an upstream that validates item IDs fails the whole request
with "Invalid 'input[N].id': 'fc_...'. Expected an ID that begins with
'ctc'", and every following message re-submits the same bad item.

Re-prefix the ID to match the type it is raised to, keeping the suffix so
the ID stays stable and unique per upstream item. IDs without a known
tool-call prefix are left alone rather than guessed at.

The lowering direction has to reverse this, because the WebSocket HTTP
bridge replays restored items back to the upstream and would otherwise lose
the upstream's own ID. normalizeLoweredFunctionItemID now maps a ctc_/tsc_
call ID back to fc_ instead of dropping it, which makes the round trip
lossless; output item IDs (ctco_/tso_) still have no function-protocol
counterpart and are still dropped. The helper was renamed from
dropInvalidLoweredFunctionItemID to match what it now does.

The stream restorer keeps the upstream ID for its own bookkeeping so later
upstream events still match the call, and emits the client-facing ID on
output_item.added/done and the custom_tool_call_input events.

Closes #6071
2026-08-22 14:03:25 +07:00
Long Li e39fce270d fix(codex): sync routed capabilities from upstream
Account model mappings decide availability, but generated Codex catalogs previously inferred capabilities from local model-name tables. Compatible upstreams can expose unknown models such as OpenCode x-preview-f-free, so reasoning levels, image input, and context limits were missing or wrong.

Sync capability metadata from the account model endpoint, enrich incomplete lists from the Models.dev provider matching the account base URL, and persist only complete snapshots. Mixed groups consume the safe intersection across schedulable accounts. When IDs sync without complete metadata, return an explicit warning and preserve the previous snapshot.

Third-party Responses providers often omit /models. If that endpoint returns 404 or 405 and the account already has concrete model mappings, use those configured upstream IDs for capability enrichment. Authentication, rate-limit, server, and network failures remain hard errors, and metadata is never guessed across providers by model name alone.

Advertise a single none choice for non-reasoning models so current Codex can select them, then omit that catalog placeholder when forwarding to compatible Responses upstreams while preserving official OpenAI request semantics.
2026-08-22 15:33:12 +09:00
Long Li 5a2f542ab0 fix(codex): prefer configured models over discovery
OpenAI groups can mix OAuth accounts with Responses-compatible API key accounts whose upstreams do not implement /models. The manifest handler previously selected one account and fetched its catalog before merging model_mapping aliases, so a permanent 404 returned 502 and hid models the administrator had already configured.\n\nTreat explicit model mappings from schedulable accounts as the authoritative Codex catalog. Build that catalog locally before account selection, preserve group filtering and final-body ETags, and retain the existing upstream discovery and failover path only when no mappings exist. Composite groups keep their existing account-first catalog behavior.
2026-08-22 14:43:40 +09:00
Long Li b16ed03cad fix(codex): align routed catalogs with actual routes
Anthropic fallbacks previously reused Antigravity defaults, leaking Gemini models into Claude-only groups. Composite aliases were also emitted with generic metadata and could be scheduled to accounts that did not own the exact mapping, while generated configs could default to a model absent from the downloaded catalog.

Keep provider defaults separated, derive alias capabilities from unique upstream targets with conservative fallback, require exact mapping ownership during scheduling, filter media targets, and choose generated config defaults from the fetched catalog.
2026-08-22 14:43:40 +09:00
Long Li 3e98a5a1ad fix(composite): route exact account model aliases
Composite model catalogs expose exact account model_mapping aliases, but request routing only considered explicit routes or model-name detection. Unprefixed aliases were selectable but unroutable.

Resolve unique exact account ownership before the detector, keep explicit routes authoritative, and fail closed when an alias is claimed across platforms.
2026-08-22 14:43:40 +09:00
Long Li e471be7302 feat(codex): complete routed model catalogs
Codex treats the downloaded model catalog as a capability contract. Slug-only entries hide supported reasoning levels, can advertise invalid image inputs, and expose automatic or media-only models in the model picker. Generate complete route-aware metadata, preserve official manifests, filter non-agent models, and compute validators from the final catalog.
2026-08-22 14:43:40 +09:00
Long Li 22e1b8144a feat(gateway): expose routed Codex model catalogs
Codex model discovery expects a top-level models manifest, but Composite and other non-OpenAI groups either reached the OpenAI live-manifest handler or had no Codex-specific response at all. API key users also had no supported way to fetch that manifest and reference it from config.toml.

Generate minimal manifests from each group's effective model list while preserving the official OpenAI live path and the ordinary /models response. Add the Use Key flow for authenticated catalog download and model_catalog_json configuration without writing the API key into the downloaded file.
2026-08-22 14:43:40 +09:00
Wesley Liddick d45135d87d Merge pull request #6068 from okbexx/fix/codex-guardian-parent-affinity
fix(openai): keep auto-review on parent account
2026-08-22 13:41:42 +08:00
Wesley Liddick d29d7f8cbc Merge pull request #6065 from chinnsenn/fix/image-generation-flows
fix(openai): stabilize oauth image generation
2026-08-22 13:35:26 +08:00
Wesley Liddick fd6cd474d6 Merge pull request #5846 from lbyxiaolizi/fix/responses-chat-malformed-tool-arguments
fix(apicompat): reject malformed tool-call arguments
2026-08-22 13:35:02 +08:00
Wesley Liddick 73f6a590bf Merge pull request #5912 from xuhaihan/fix/deepseek-responses-client-tools
fix(deepseek): adapt Codex client tools for Responses
2026-08-22 13:34:49 +08:00
Wesley Liddick ffc01f9c66 Merge pull request #5864 from wucm667/fix/issue-5850-http-bridge-replay
fix(openai): avoid duplicate HTTP bridge replay
2026-08-22 13:34:32 +08:00
Wesley Liddick 6244090c1c Merge pull request #5487 from an-epiphany/fix/file-part-min
fix(apicompat): chat/completions 的 file part 转换为 Responses input_file,不再静默丢弃
2026-08-22 13:34:18 +08:00
Wesley Liddick 844b118785 Merge pull request #5938 from Hakunm/fix/google-one-model-catalog
fix(gemini): 限制 Google One OAuth 模型目录 / constrain Google One model catalog
2026-08-22 13:34:05 +08:00
alfadb 86470628df feat(ollama): 对 Ollama Cloud 账号 clamp max_tokens 上限 2026-08-22 12:38:05 +08:00