3587 Commits

Author SHA1 Message Date
shaw
2f70d965bf chore: update sponsors 2026-05-25 19:06:55 +08:00
shaw
53acde1efd style: fix lint errors in response.failed SSE writer
Errcheck flagged three unchecked strings.Builder.WriteString calls and
gofmt rejected over-aligned trailing comment in the route table.

Rewrite writeResponsesFailedSSE with json.Marshal on typed structs
instead of Builder+strconv.Quote. Same wire format, but:
- no unchecked Write returns to silence
- strict JSON escaping (strconv.Quote emits \a and \v which are not
  valid JSON; Marshal handles all runes correctly)
- omitempty model field via struct tag instead of conditional Builder
- consistent with the json.Marshal style used elsewhere in handler/

Collapse trailing comment whitespace in stream_error_event_test.go to
satisfy gofmt.

All 30+ subtests in the package still pass.
2026-05-25 18:16:46 +08:00
Wesley Liddick
a18738b29e
Merge pull request #2732 from wminjay/fix/responses-stream-failed-event
fix(openai): emit response.failed when /v1/responses SSE aborted post-flush
2026-05-25 18:12:25 +08:00
Wesley Liddick
2fb9fb2f71
Merge pull request #2747 from siyuan-123/fix/ws-tool-output-continuation
修复 WS 协议下工具输出续链识别问题
2026-05-25 17:58:00 +08:00
siyuan
fc66cd704a fix: recognize codex tool outputs in ws continuation 2026-05-25 10:46:58 +08:00
Jamie Wong
b34cc71bee fix(openai): also emit response.failed in ensureForwardErrorResponse after Writer.Written
Case B: when a slot wait flushes SSE ping comments first (Writer.Written
becomes true), the previous ensureForwardErrorResponse short-circuited
on `c.Writer.Written()` and returned false without notifying the client.
Subsequent upstream errors (http2 timeout, stream INTERNAL_ERROR, etc.)
produced silent EOF; Codex CLI reported "stream closed before
response.completed" just like the user-slot timeout case.

Remove the Written() early return; coerce streamStarted to true when
Writer has already been written to, and let handleStreamingAwareError
walk the existing logic — which now (thanks to the previous commits)
emits a protocol-compliant response.failed for /responses paths and the
legacy `event: error` for others.

Update tests that previously asserted "do not override written response":
the new contract is to *append* an SSE terminal frame so the client sees
a clean close instead of EOF. recoverResponsesPanic inherits this fix.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 22:00:56 +08:00
Jamie Wong
cff2f291be fix(openai): also match bare /responses route in handleStreamingAwareError
The first revision compared GetInboundEndpoint(c) against EndpointResponses
("/v1/responses"). NormalizeInboundEndpoint only recognizes paths that
contain the literal "/v1/responses" substring, but the project actually
registers six /responses routes — three of which (top-level
r.POST("/responses", ...) and codexDirect's "/backend-api/codex/responses")
have FullPath values without the "/v1" prefix and therefore fall through
to the default branch.

Codex CLI users targeting the bare /responses route at the production
deployment (observed 2026-05-24 ~11:05 UTC, user 16) never reached the
new writeResponsesFailedSSE path: the endpoint check was false, the
legacy `event: error` frame fired, and the strict SDK kept reporting
"stream closed before response.completed".

Replace the strict equality check with inboundIsResponses(c), which
uses suffix detection on FullPath (falling back to URL.Path when
FullPath is empty in test fixtures) and covers all six route variants:

  /v1/responses[/...]
  /responses[/...]
  /backend-api/codex/responses[/...]

Add test table covering all routes plus negative cases.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 19:32:08 +08:00
Jamie Wong
5e5c2062bf fix(openai): emit response.failed for /v1/responses after stream started
When /v1/responses streaming hits the user/account concurrency wait, the
wait loop sends SSE ping comments to keep the connection alive, which
flushes HTTP 200 + headers. If the wait then times out (or any other
post-flush error fires), handleStreamingAwareError previously emitted a
generic `event: error` frame. Codex CLI requires the stream to end with
a Responses terminal event (response.completed/failed/incomplete/cancelled),
so it reports "stream closed before response.completed" and the user-facing
rate-limit intent is lost.

This change detects inbound = /v1/responses in both handleStreamingAwareError
implementations and emits a protocol-compliant response.failed event whose
field set mirrors apicompat.makeResponsesCompletedEvent
(id/object/model/status/output/error). The synthetic id reuses
ctxkey.RequestID so client errors can be grepped against server logs.
sequence_number is intentionally omitted to preserve monotonicity on streams
that already emitted real events.

Other inbound endpoints (/v1/chat/completions, /v1/messages) keep their
legacy formats untouched.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 10:58:29 +08:00
github-actions[bot]
63b0631a58 chore: sync VERSION to 0.1.130 [skip ci] 2026-05-23 06:40:10 +00:00
shaw
0cfabaa82e fix(i18n): escape at-sign in email whitelist placeholder
Escape the at-sign in email whitelist placeholder to avoid Vue I18n linked message parsing errors on the settings page.
2026-05-23 14:18:20 +08:00
shaw
0430899748 feat(admin): add compact proxy IP resource link
Add a low-visibility proxy IP resource link near proxy-related controls.

- Show the link beside account proxy selectors

- Show the link in the create proxy dialog tab row

- Keep the entry inline to avoid interrupting form workflows
2026-05-23 14:18:19 +08:00
Wesley Liddick
3c5a444802
Merge pull request #2698 from deqiying/fix/log-real-client-ip
fix: 修复反代部署下拒绝日志客户端 IP 不准确
2026-05-23 11:08:47 +08:00
shaw
b6c0b40848 fix: update x/net vulnerability dependency 2026-05-23 10:55:44 +08:00
shaw
1e406fed52 fix: optimize OpenAI account cooldown scheduling 2026-05-23 10:18:43 +08:00
deqiying
0af44ce4c2 fix: 修复反代部署下拒绝日志客户端 IP 不准确
将 OpenAI codex_cli_only 拒绝诊断日志中的 request_client_ip
改为复用 ip.GetClientIP,与 usage 记录和 access log 的真实客户端
IP 解析逻辑保持一致。

保留 request_remote_addr 用于排查底层 Docker/反代 peer 地址,并补充
单元测试覆盖反代头与 remote addr 分离的场景。
2026-05-22 23:28:21 +08:00
Wesley Liddick
f59d9a5f8e
Merge pull request #2674 from wucm667/feat/moderation-per-model-toggle
feat(risk-control): 内容审计支持按模型生效
2026-05-22 20:10:38 +08:00
Wesley Liddick
301032dc72
Merge pull request #2672 from wucm667/feat/email-whitelist-wildcard-suffix
feat(registration): 邮箱白名单支持后缀通配符匹配(*.edu.cn)
2026-05-22 17:33:29 +08:00
Wesley Liddick
a5efb84fa0
Merge pull request #2656 from wucm667/fix/apicompat-developer-role-to-system
fix(apicompat): Responses 转 Chat Completions 时 developer role 映射为 system
2026-05-22 17:32:47 +08:00
Wesley Liddick
9f91a8af17
Merge pull request #2662 from touwaeriol/feat/bedrock-cc-compat
feat(bedrock): add Claude Code compatibility for AWS Bedrock
2026-05-22 17:32:11 +08:00
Wesley Liddick
a33a294970
Merge pull request #2658 from wucm667/feat/account-test-chat-completions-path
feat(account): 测试连接支持 OpenAI-compatible Chat Completions 路径
2026-05-22 17:31:14 +08:00
Wesley Liddick
ac72b01d89
Merge pull request #2681 from wucm667/fix/moderation-dedupe-agent-loop
fix(risk-control): Agent 工具循环中同一用户消息重复审计去重
2026-05-22 17:29:22 +08:00
Wesley Liddick
e674a5628c
Merge pull request #2682 from Xch13/fix-cache-hit-rate
fix(frontend): 修正 Cache Hit Rate 计算分母,包含全部 prompt tokens
2026-05-22 17:27:26 +08:00
Wesley Liddick
85e60b4f51
Merge pull request #2687 from wucm667/fix/audit-exception-js-cookie
fix(deps): 升级 js-cookie 解决 GHSA-qjx8-664m-686j 阻塞 frontend-security CI
2026-05-22 17:14:59 +08:00
wucm667
199a5bcc69 fix(risk-control): Agent 工具循环中同一用户消息重复审计去重
末尾 role 检查方案:当 messages / input / contents 数组末尾一项不是用户消息
(而是 assistant、tool / function_call_output 等)时,直接跳过内容审计,
从而避免 Agent 工具循环中同一用户输入被反复审计、计费、写日志。

Fixes #2678
2026-05-22 14:54:06 +08:00
wucm667
ffd53343bb fix(deps): 升级 js-cookie 修复安全审计 2026-05-22 13:55:27 +08:00
Xch13
6ba20acd66 fix(frontend): correct Cache Hit Rate denominator to include all prompt tokens
Cache Hit Rate was calculated as cache_read / (cache_read + cache_creation),
which always yields 100% for OpenAI models since cache_creation is never
reported by the OpenAI API. The denominator should include all prompt tokens
(input_tokens + cache_read_tokens + cache_creation_tokens) so the rate
reflects the actual percentage of input tokens served from cache.

Fixes #2291
2026-05-22 11:45:33 +08:00
wucm667
0d5c6f7cc7 feat(risk-control): 内容审计支持按模型生效 2026-05-21 21:18:43 +08:00
wucm667
a5b9b68b76 feat(registration): 支持邮箱白名单后缀通配符 2026-05-21 21:02:26 +08:00
wucm667
ca60cede14 feat(account): 支持测试连接 Chat Completions 路径 2026-05-21 16:37:20 +08:00
wucm667
c4d7edba08 fix(apicompat): map developer role to system 2026-05-21 16:37:05 +08:00
shaw
16793d3af0 chore: update sponsors 2026-05-21 15:26:20 +08:00
shaw
aae20ef437 fix(oidc): harden verified-email fast path 2026-05-21 15:19:29 +08:00
Wesley Liddick
35901a174b
Merge pull request #2655 from ye4241/feat/oidc-trust-verified-email-fast-path
feat(oidc): 上游邮箱已验证时跳过 choice 页直接登录注册
2026-05-21 14:47:08 +08:00
shaw
a613a587ba feat: add subscription expiry email toggle 2026-05-21 14:27:50 +08:00
ye4241
55554adc18 chore(oidc): 回应 Copilot review
- ProviderType 从 identity.ProviderType 取(不再硬编码)
- fast-path 日志改用 infraerrors.Reason(err) 避免泄露 PII / 降噪
2026-05-21 13:32:20 +08:00
ye4241
39fe7aa0eb feat(oidc): 上游邮箱已验证时跳过 choice 页直接登录注册
当前 OIDC 首次登录无条件创建 choose_account_action_required 的 pending
session,即使 force_email_on_third_party_signup 关闭,前端仍然会强制
弹出"创建账号 / 绑定已有账号"的二选一界面,并展示内部合成邮箱
(oidc-xxx@oidc-connect.invalid),用户体验差。

本次复用已存在的 LoginOrRegisterVerifiedEmailOAuth 路径(原本仅供
github/google 使用),在以下条件全部满足时跳过 choice 页,直接
信任上游身份完成注册/登录:

- force_email_on_third_party_signup = false
- 邀请码模式未启用
- 上游声明 email_verified = true 且 compat_email 非空
- 本地不存在同邮箱已有账号

失败时(如邮箱后缀不在白名单、注册关闭等)自动回退到现有 choice
流程,行为完全向后兼容。

测试覆盖:
- TestTryOIDCVerifiedEmailFastPathCreatesUserAndIdentity
- TestTryOIDCVerifiedEmailFastPathSkippedWhenInvitationCodeRequired
- TestTryOIDCVerifiedEmailFastPathSkippedWhenForceEmailEnabled
2026-05-21 13:32:20 +08:00
erio
fe1c6c958b feat(bedrock): add Claude Code compatibility for AWS Bedrock
- Export ApplyBedrockCCCompat() in GatewayService, called after channel
  model mapping to ensure mapped model ID is used for Opus 4.7+ detection
- Add sanitizeBedrockCCFields(): remove service_tier/interface_geo/
  context_management, inject max_tokens/anthropic_version defaults
- Add sanitizeBedrockCCBetaTokens(): filter anthropic_beta to keep only
  Bedrock-supported tokens, reusing autoInjectBedrockBetaTokens and
  filterBedrockBetaTokens for consistent rules
- Remove unsupported beta tokens (interleaved-thinking, context-management)
  from whitelist based on AWS official docs
- Simplify IsBedrockCCCompatEnabled() to check boolean toggle directly,
  applying CC compat to all accounts regardless of platform
- Add unit tests for IsBedrockCCCompatEnabled (8 cases),
  sanitizeBedrockCCFields (8 cases), sanitizeBedrockCCBetaTokens (7 cases)
- Update bedrock beta policy tests for removed auto-injection
2026-05-21 11:46:24 +08:00
Wesley Liddick
bd3d4d9a24
Merge pull request #2399 from gaoren002/fix/openai-image-upstream-errors
fix(openai): surface image moderation errors
2026-05-21 11:31:22 +08:00
Wesley Liddick
a60a349ecf
Merge pull request #2375 from gaoren002/fix/account-delete-scheduler-cache
fix: clear scheduler cache when deleting accounts
2026-05-21 11:31:05 +08:00
Wesley Liddick
131d4b3050
Merge pull request #2374 from gaoren002/fix/openai-refresh-token-reused
fix: mark reused refresh tokens non-retryable and unschedule errored accounts
2026-05-21 11:30:52 +08:00
shaw
9673a22f26 fix(i18n):
去除兑换码批量修改重复的翻译 key

  PR #2613 与 PR #2615 各自独立添加了同一组批量修改 i18n key,
  导致 vue-tsc 报 TS1117 错误。保留 Title Case 一组,删除重复定义。
2026-05-21 11:12:32 +08:00
Wesley Liddick
eda04c6129
Merge pull request #2615 from wucm667/feat/redeem-code-batch-update
feat(redeem): 兑换码支持批量修改
2026-05-21 10:39:46 +08:00
Wesley Liddick
b106192ee2
Merge pull request #2648 from DaydreamCoding/fix/user-provider-default-grants-check
fix(auth): user_provider_default_grants 加入 github/google/dingtalk
2026-05-21 10:38:34 +08:00
Wesley Liddick
d3c4e50753
Merge pull request #2645 from lyen1688/fix/trusted-forwarded-ip-acl
PR:为 API Key IP 白/黑名单增加可配置的反代真实 IP 判断
2026-05-21 10:34:28 +08:00
DaydreamCoding
4bfb707ff3 fix(auth): user_provider_default_grants 加入 github/google/dingtalk
migration 135/136 把 github、google、dingtalk 加到 users / auth_identities /
auth_identity_channels / pending_auth_sessions 的 check 约束时,漏改
user_provider_default_grants。一旦管理员开启 grant_on_first_bind,OAuth 首次
绑定就会在 INSERT user_provider_default_grants 时撞约束,触发 500。
2026-05-21 00:48:38 +08:00
lyen1688
1d2445ff52 修复 API Key ACL 开关的 CI 校验 2026-05-20 23:51:39 +08:00
lyen1688
08c8c67df7 为 API Key ACL 增加反代真实 IP 开关 2026-05-20 22:51:46 +08:00
Wesley Liddick
e5d6f1727f
Merge pull request #2641 from Arron196/fix/channel-monitor-responses-reasoning
fix(channel-monitor): 兼容 Responses reasoning 输出
2026-05-20 22:36:46 +08:00
Wesley Liddick
f2d072ffc7
Merge pull request #2643 from Arron196/fix/ops-sla-local-client-errors
fix(ops): 排除本地客户端限制错误的 SLA 计数
2026-05-20 22:36:02 +08:00
Wesley Liddick
99261741af
Merge pull request #2642 from touwaeriol/feat/bedrock-cc-compat
feat(bedrock): add Claude Code compatibility transformations
2026-05-20 22:35:30 +08:00