mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 09:20:22 +08:00
fix: Codex 反代添加 chatgpt-account-id 请求头
通过 contextvars 将 OAuth 认证配置中的 account_id 从 wrap_request()传递到 extra_headers(),修复实际请求时缺少 chatgpt-account-id 头导致的错误。
This commit is contained in:
44
src/services/provider/adapters/codex/context.py
Normal file
44
src/services/provider/adapters/codex/context.py
Normal file
@@ -0,0 +1,44 @@
|
||||
"""Codex request context using contextvars.
|
||||
|
||||
Similar to Kiro's context pattern, this bridges data from `CodexOAuthEnvelope.wrap_request()`
|
||||
(which receives the decrypted auth_config) to `extra_headers()` which is parameterless.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextvars
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class CodexRequestContext:
|
||||
"""Per-request context for the Codex adapter.
|
||||
|
||||
This bridges data from `CodexOAuthEnvelope.wrap_request()` (which receives the
|
||||
decrypted auth_config) to other layers that only expose parameterless hooks
|
||||
(extra_headers).
|
||||
"""
|
||||
|
||||
account_id: str | None = None
|
||||
user_id: str | None = None
|
||||
|
||||
|
||||
_codex_request_context: contextvars.ContextVar[CodexRequestContext | None] = contextvars.ContextVar(
|
||||
"codex_request_context",
|
||||
default=None,
|
||||
)
|
||||
|
||||
|
||||
def set_codex_request_context(ctx: CodexRequestContext | None) -> None:
|
||||
_codex_request_context.set(ctx)
|
||||
|
||||
|
||||
def get_codex_request_context() -> CodexRequestContext | None:
|
||||
return _codex_request_context.get()
|
||||
|
||||
|
||||
__all__ = [
|
||||
"CodexRequestContext",
|
||||
"get_codex_request_context",
|
||||
"set_codex_request_context",
|
||||
]
|
||||
@@ -7,6 +7,9 @@ to avoid upstream blocks (Cloudflare, etc.).
|
||||
Request/response shape quirks should live in the conversion layer as a same-format
|
||||
variant (`target_variant="codex"` in the `openai:cli` normalizer). This envelope
|
||||
only adds headers and keeps the rest as a no-op wrapper.
|
||||
|
||||
We use contextvars to pass request-scoped values (account_id) from wrap_request()
|
||||
to extra_headers().
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -15,6 +18,11 @@ import uuid
|
||||
from typing import Any
|
||||
|
||||
from src.config.settings import config
|
||||
from src.services.provider.adapters.codex.context import (
|
||||
CodexRequestContext,
|
||||
get_codex_request_context,
|
||||
set_codex_request_context,
|
||||
)
|
||||
from src.services.provider.request_context import get_selected_base_url
|
||||
|
||||
|
||||
@@ -38,18 +46,31 @@ class CodexOAuthEnvelope:
|
||||
if ua:
|
||||
headers["User-Agent"] = ua
|
||||
|
||||
# Add chatgpt-account-id from context (set by wrap_request)
|
||||
ctx = get_codex_request_context()
|
||||
if ctx and ctx.account_id:
|
||||
headers["chatgpt-account-id"] = ctx.account_id
|
||||
|
||||
return headers
|
||||
|
||||
def wrap_request(
|
||||
self,
|
||||
request_body: dict[str, Any],
|
||||
*,
|
||||
model: str,
|
||||
model: str, # noqa: ARG002
|
||||
url_model: str | None,
|
||||
decrypted_auth_config: dict[str, Any] | None,
|
||||
) -> tuple[dict[str, Any], str | None]:
|
||||
# Extract account_id from auth_config and set context for extra_headers()
|
||||
account_id = (decrypted_auth_config or {}).get("account_id")
|
||||
user_id = (decrypted_auth_config or {}).get("user_id")
|
||||
set_codex_request_context(
|
||||
CodexRequestContext(
|
||||
account_id=str(account_id) if account_id else None,
|
||||
user_id=str(user_id) if user_id else None,
|
||||
)
|
||||
)
|
||||
# No wire envelope for Codex; keep request body as-is.
|
||||
_ = model, decrypted_auth_config
|
||||
return request_body, url_model
|
||||
|
||||
def unwrap_response(self, data: Any) -> Any:
|
||||
|
||||
Reference in New Issue
Block a user