mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +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
|
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
|
variant (`target_variant="codex"` in the `openai:cli` normalizer). This envelope
|
||||||
only adds headers and keeps the rest as a no-op wrapper.
|
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
|
from __future__ import annotations
|
||||||
@@ -15,6 +18,11 @@ import uuid
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from src.config.settings import config
|
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
|
from src.services.provider.request_context import get_selected_base_url
|
||||||
|
|
||||||
|
|
||||||
@@ -38,18 +46,31 @@ class CodexOAuthEnvelope:
|
|||||||
if ua:
|
if ua:
|
||||||
headers["User-Agent"] = 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
|
return headers
|
||||||
|
|
||||||
def wrap_request(
|
def wrap_request(
|
||||||
self,
|
self,
|
||||||
request_body: dict[str, Any],
|
request_body: dict[str, Any],
|
||||||
*,
|
*,
|
||||||
model: str,
|
model: str, # noqa: ARG002
|
||||||
url_model: str | None,
|
url_model: str | None,
|
||||||
decrypted_auth_config: dict[str, Any] | None,
|
decrypted_auth_config: dict[str, Any] | None,
|
||||||
) -> tuple[dict[str, Any], str | 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.
|
# No wire envelope for Codex; keep request body as-is.
|
||||||
_ = model, decrypted_auth_config
|
|
||||||
return request_body, url_model
|
return request_body, url_model
|
||||||
|
|
||||||
def unwrap_response(self, data: Any) -> Any:
|
def unwrap_response(self, data: Any) -> Any:
|
||||||
|
|||||||
Reference in New Issue
Block a user