Skip to content

修复 OpenAI TLS 指纹模板 User-Agent 回退#29

Open
lyen1688 wants to merge 742 commits into
IanShaw027:personal-devfrom
lyen1688:fix/openai-tls-profile-user-agent-fallback
Open

修复 OpenAI TLS 指纹模板 User-Agent 回退#29
lyen1688 wants to merge 742 commits into
IanShaw027:personal-devfrom
lyen1688:fix/openai-tls-profile-user-agent-fallback

Conversation

@lyen1688

Copy link
Copy Markdown

变更内容

  • 为 TLS 指纹模板增加 user_agent 字段,支持创建、更新、导入采集样本时保存对应 User-Agent。
  • 创建 TLS 指纹模板时,“解析 YAML”会自动提取 User-Agent,并自动填充 extensions 等扩展字段。
  • OpenAI TLS 指纹应用时统一 User-Agent 优先级:
    1. 指纹路由规则的 upstream_user_agent
    2. 最终命中的 TLS 指纹模板 user_agent
    3. 开启透传时保留客户端 User-Agent
    4. 未开启透传时使用后台 OpenAI Codex UA 设置
    5. 设置为空时回退内置默认 Codex UA
  • 修正两级 TLS 指纹选择逻辑:路由命中具体模板时使用路由模板;路由未命中或模板不存在时回落到一级选择的模板。
  • 图片生成、WS、Responses 探测、CC 转 Messages 兼容转发等 OpenAI 请求路径也接入同一套 UA 回退逻辑,避免模板缺 UA 时暴露 Go 默认 UA。

验证

  • go test ./...
  • pnpm vitest run src/utils/__tests__/tlsFingerprintYaml.spec.ts
  • pnpm run build
  • git diff --check

IanShaw027 added 30 commits May 29, 2026 10:34
…l, ban exemptions

- Attention threshold: a non-hit highest-score >= the configured percent
  is stored as a non-hit summary only (no hit/ban/block side effects).
  Configurable via record_attention_inputs and attention_threshold.
- API key accounts: keys can be paired with an account_email so the
  admin UI surfaces which account each key belongs to.
- Auto-ban exemptions: auto_ban_exempt_user_ids and
  auto_ban_exempt_user_emails skip the disable step but still block
  and email on hit.
- Frontend wires the new fields through the riskControl API,
  RiskControlView UI, and matching spec coverage.
vue-i18n parses a bare "@" as the start of a linked-message reference
("@:foo" / "@.lower:foo"), so example email addresses like
"email@example.com" embedded in placeholder strings raised
"Invalid linked format" and prevented the locale from initializing.

Wrap every bare "@" with {'@'} (matching the existing escape style used
elsewhere in the same files) so the literal stays in the string.
…revious_response_id and orphan tool outputs

- Stop retrying response.failed events whose error indicates context window
  overflow; let the failed frame pass through so clients see the real cause.
- Align HTTP /v1/responses invalid_encrypted_content recovery with the WS path:
  also drop previous_response_id when there is no function_call_output in flight.
- Add a one-shot retry that drops previous_response_id when upstream returns
  "Unsupported parameter: previous_response_id".
- In codex compat fallback for "no tool call found ..." errors, prune orphan
  function_call_output items whose call_id has no matching function_call /
  item_reference, and drop the now-stale previous_response_id.
- Append a synthetic data: [DONE] terminator after streaming errors on the
  chat-completions path so OpenAI SDKs close the stream cleanly instead of
  waiting for read timeout. /v1/responses keeps response.failed.
…election failure messages

- Add account_response_rewrite_rule service with credentials-aware persistence and a
  matcher keyed on raw upstream status code + body keywords.
- Wire the matcher into OpenAI failover-exhausted handling so per-account rules
  override the default error mapping; passthrough rules still apply afterwards.
- Replace the generic "Service temporarily unavailable" with a context-aware
  buildOpenAISelectionFailureMessage that surfaces "no account supports model X"
  versus other selection failures across /v1/responses, /v1/chat/completions,
  /v1/embeddings and /v1/images.
- Plumb the active account through handleFailoverExhausted so the rewrite
  matcher can consult the account configuration.
- Add response rewrite rules UI to Create/Edit Account modals with i18n.
- Add account_scheduling_threshold_eval/_reason services that pause an account
  when its native usage window crosses an admin-configured percentage; reuse
  the temp_unschedulable_until column to keep history with structured reason
  payloads.
- Plumb the threshold filter through GatewayService and OpenAIGatewayService
  selection paths (snapshot list, recheck, getSchedulableAccount) so paused
  accounts are excluded uniformly across schedulers.
- Persist account_scheduling_thresholds as a system setting (per platform,
  100 = disabled), expose admin endpoints, and add a Settings UI section with
  per-platform inputs and i18n strings (EN/ZH).
- Store a structured fallback reason payload when SetTempUnschedulable receives
  an empty reason so downstream UIs always have something parseable.
…uler snapshot

- After fetching Kiro quota for an account, write {kiro_sched_utilization,
  kiro_sched_usage_updated_at, kiro_sched_reset_at} into account.extra so the
  per-platform scheduling threshold filter has a fresh signal to act on.
- After fetching Antigravity model quotas, choose the worst (highest
  utilization, then latest reset) scope and persist
  {antigravity_sched_utilization, antigravity_sched_usage_updated_at,
  antigravity_sched_reset_at} the same way.
- Skip persistence when the fetch errored, was forbidden or needs reauth so
  stale data does not get promoted into the snapshot.
…s scheduling

When an OpenAI account hits a 429 with "Rate limit reached for gpt-image-* ...
on input-images per ..." the limit is image-route specific (codex + web2api
share the per-account input-image quota). Previously we still set
RateLimited / ran the OAuth runtime block on the whole account, so the same
account could not serve chat/responses traffic until the cooldown elapsed.

Now the image-rate-limit message is detected and only marks both image route
prefixes' reset_at; the global rate-limited timestamp and runtime block path
are skipped so text routes keep flowing.
- MediaObjectStore: add PresignGetObject so private downloads are served via
  short-lived signed URLs instead of streaming through the gateway.
- MediaRepository: add GetByObjectKey for resolving an asset from its
  bucket+key, used to materialize public URLs on read paths.
- MediaService.Create*DownloadURL now passes the asset to the URL builder so
  it can presign per-asset; PublicURL falls back to GetByID lookup before
  composing the public base URL.
- Update mocks/stubs across handler and service tests so the new repo and
  store methods compile.
…r inputs

- Insert the existing OpenAI overload special branch into the error-handling
  layering order so it is preserved alongside the new account-level rewrites.
- Carve out the explicit local selection-failure cases (compact_not_supported,
  No available compatible accounts, etc.) from the generic 'no available
  accounts' message rewrite so already-precise messages are not regressed.
- Clarify that account-level rewrite rules match against the raw upstream
  status code and body, not the gateway-mapped client-facing status.
…rors

Kiro upstream transport failures (DoWithTLS returning err — typically AWS Q
RST manifesting as `context canceled`) used to short-circuit the failover
loop: handler returned 502 immediately without switching accounts and the
account was never marked. Subsequent requests kept landing on the same dead
upstream.

Now the transport-err branch:
- Distinguishes real client disconnect (gin request context already canceled)
  from upstream-induced cancellation; the former still passes through
  silently.
- Marks the offending account temp-unschedulable for 2 min (with cache sync
  + scheduling-blocker notification) so the scheduler skips it during
  recovery.
- Returns *UpstreamFailoverError so the gateway main loop fails over to the
  next compatible account.

Removes the in-service c.JSON(502) — the handler main loop owns the final
response so failover-exhausted paths can format it consistently.

Covers both the streaming entry and the free-thinking double-request path.
…happened

Chat-completions / embeddings / images handlers used to fall back to a
generic 502 "Upstream request failed" when the failover loop exited
without ever talking to upstream (e.g. all accounts filtered out before
the first dispatch). 502 misleads clients into thinking upstream actually
failed; the real cause is local routing capacity.

Switch the no-failover branch to 503 + a routing-capacity-limited ops
marker so dashboards and clients can tell the two situations apart.
The post-failover branch keeps the upstream-derived status via
handleFailoverExhausted.
…essage guard

- dropOrphanFunctionCallOutputs only filtered "function_call_output" items,
  but Codex tool-call outputs come in several variants (tracked by
  isCodexToolCallOutputItemType). Use the helper so all of them participate
  in the orphan-pairing pass instead of only the legacy type slipping
  through.

- isOpenAIImageGenerationRateLimitMessage matched bare "gpt-image" in any
  message, which over-triggers when "gpt-image*" appears as a model name
  in non-image account-level 429s. Require an accompanying quota keyword
  (limit / quota / per ) so only true image-quota messages activate the
  image-route bypass.
Add archive file support to the account import dialog, allowing users
to upload .zip/.cpa files directly. The frontend auto-detects file type
and routes to the appropriate backend endpoint. Also fix codex session
dedup logic to use email+account_id composite key, preventing false
duplicates for team accounts sharing the same account_id.
…fallback name

OpenAI org selection now checks the access_token `poid` claim first to
pick the correct team workspace, falling back to default-org and then
role/title heuristics. Kiro OAuth account naming extracts the profile ID
from user_id when name/email are absent.
… selection exhausted message

Add shouldSuppressForwardErrorResponse to skip writing fallback error
bodies when the client has already disconnected (context.Canceled).
Split buildOpenAISelectionExhaustedMessage from the failure variant so
that local-exclusion retries return the generic fallback instead of
leaking model-specific details.
IanShaw027 and others added 25 commits June 19, 2026 15:34
Strengthen idempotency key generation for Airwallex, tighten Stripe
refund error classification, and add wxpay duplicate-refund guard.
Add upstream source metadata to ops error logger, extend stream error
event classification, and surface forward-error detail in diagnostics.
Broaden content moderation exemption logic and add tests covering
boundary conditions for group-based bypass paths.
Refine account selection logic, improve channel availability checks,
and add comprehensive scheduler rotation tests.
Simplify request conversion, fix response field mapping for tool-use
content blocks, and add cc_to_anthropic_response tests.
Introduce messages-to-chat-completions fallback path, extend endpoint
routing logic, and add raw/stream test coverage for edge cases.
Extend delta-shadow continuation logic with strict ordering, add
forwarder success-path tests, and fix pool/state-store edge cases.
Adjust config defaults, add http_upstream dial tests, harden deploy
script restart logic, and extend account modals with new form fields.
…idge

- Map web_fetch_* tool types in anthropic-to-responses conversion
- Convert unsupported Responses tool types to function fallback instead of error
- Deduplicate native server tools (web_search, web_fetch) in CC bridge
- Add default parameters/descriptions for known server tools
…covery for function_call_output

- Raise default session_idle_ttl_seconds from 30 to 600 for better delta-chain hit rate
- Unify neutral idle TTL with session idle TTL (remove hardcoded 60s constant)
- Add configurable outbound_payload_http_fallback_threshold_bytes (0 inherits read limit)
- Enhance previous_response_not_found recovery to replay full payload with function_call_output context
- Make shouldPreflightFallbackOpenAIWSPayloadToHTTP a method on service for config access
…am accounts

- Broaden TextEndpointAutoRouteEnabled to support both OpenAI and Anthropic platforms
- Add raw CC/Responses forwarder for openai_compat_cc_upstream accounts
- Allow CC-upstream accounts with auto-route in OpenAI compat ingress filter
- Guard ShouldForwardOpenAITextMessagesViaChatCompletions to OpenAI-only path
- Generalize frontend toggle visibility via supportsTextEndpointAutoRoute helper
- Implement GeminiMessagesCompatService.ForwardAsResponses for Responses-shaped clients
- Surface cache_read_input_tokens and cache_creation_input_tokens in Claude-format response
…test

Fixes test setup to supply schedulable account via repo mock, matching
the runtime path that now checks account-level model mappings.
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 620c0a71-15ad-4982-9c30-a8691cb53f82

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 21, 2026

Copy link
Copy Markdown

All contributors have signed the CLA. ✅
Posted by the CLA Assistant Lite bot.

@lyen1688

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@lyen1688

Copy link
Copy Markdown
Author

recheck

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants