mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-01 17:00:21 +08:00
refactor(codex): 移除 envelope/request_patching 层,用 context var 统一 compact 状态判断
- 删除 CodexOAuthEnvelope 和 request_patching 模块,Codex 不再需要 envelope 层 - 移除 _aether_compact 请求体内部标记,改用 is_codex_compact_request() 集中查询 - 简化 OpenAI CLI adapter,移除 Codex 专用的 get_cli_extra_headers/build_test_request_body 逻辑 - 移除 Codex behavior variant 注册(same_format/cross_format) - normalizer patch_same_format_request 对 codex 变为 no-op - 更新相关测试适配新的架构
This commit is contained in:
@@ -51,7 +51,6 @@ class _DummyCliStreamHandler(CliStreamMixin):
|
||||
return out
|
||||
|
||||
def prepare_provider_request_body(self, request_body: dict[str, Any]) -> dict[str, Any]:
|
||||
request_body.pop("_aether_compact", None)
|
||||
request_body["input"][0]["content"][0]["text"] = "prepared"
|
||||
return request_body
|
||||
|
||||
@@ -116,7 +115,6 @@ async def test_execute_stream_request_does_not_mutate_original_request_body(
|
||||
|
||||
original_request_body = {
|
||||
"model": "gpt-test",
|
||||
"_aether_compact": True,
|
||||
"input": [
|
||||
{
|
||||
"role": "user",
|
||||
@@ -141,6 +139,5 @@ async def test_execute_stream_request_does_not_mutate_original_request_body(
|
||||
|
||||
assert original_request_body == snapshot
|
||||
assert handler._request_builder.request_body is not None
|
||||
assert "_aether_compact" not in handler._request_builder.request_body
|
||||
assert handler._request_builder.request_body["input"][0]["content"][0]["text"] == "prepared"
|
||||
assert handler._request_builder.request_body["input"][0]["content"][-1]["text"] == "finalized"
|
||||
|
||||
@@ -1,144 +1,20 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from types import SimpleNamespace
|
||||
from typing import cast
|
||||
|
||||
import jwt
|
||||
import pytest
|
||||
|
||||
from src.api.handlers.base.request_builder import PassthroughRequestBuilder
|
||||
from src.services.provider.adapters.codex.context import set_codex_request_context
|
||||
from src.services.provider.adapters.codex.request_patching import (
|
||||
maybe_patch_request_for_codex,
|
||||
patch_openai_cli_request_for_codex,
|
||||
)
|
||||
from src.services.provider.envelope import ProviderEnvelope
|
||||
from src.services.provider.behavior import get_provider_behavior
|
||||
|
||||
|
||||
def test_patch_openai_cli_request_for_codex_is_passthrough_except_internal_sentinel() -> None:
|
||||
req = {
|
||||
"model": "gpt-test",
|
||||
"input": [
|
||||
{
|
||||
"type": "message",
|
||||
"role": "system",
|
||||
"content": [{"type": "input_text", "text": "Hello"}],
|
||||
}
|
||||
],
|
||||
"store": True,
|
||||
"stream": False,
|
||||
"instructions": "keep",
|
||||
"include": ["foo"],
|
||||
"parallel_tool_calls": False,
|
||||
"temperature": 0.7,
|
||||
"context_management": {"compaction": {"type": "summary"}},
|
||||
"user": "u_123",
|
||||
"_aether_compact": True,
|
||||
}
|
||||
out = patch_openai_cli_request_for_codex(req)
|
||||
def test_codex_provider_behavior_has_no_runtime_envelope_or_variants() -> None:
|
||||
behavior = get_provider_behavior(provider_type="codex", endpoint_sig="openai:cli")
|
||||
|
||||
assert out is not req
|
||||
assert "_aether_compact" not in out
|
||||
assert out["store"] is True
|
||||
assert out["stream"] is False
|
||||
assert out["instructions"] == "keep"
|
||||
assert out["include"] == ["foo"]
|
||||
assert out["parallel_tool_calls"] is False
|
||||
assert out["temperature"] == 0.7
|
||||
assert out["context_management"] == {"compaction": {"type": "summary"}}
|
||||
assert out["user"] == "u_123"
|
||||
assert out["input"][0]["role"] == "system"
|
||||
|
||||
|
||||
def test_patch_openai_cli_request_for_codex_preserves_existing_prompt_cache_key() -> None:
|
||||
req = {"model": "gpt-test", "input": [], "prompt_cache_key": "client-cache-key"}
|
||||
|
||||
out = patch_openai_cli_request_for_codex(req)
|
||||
|
||||
assert out["prompt_cache_key"] == "client-cache-key"
|
||||
|
||||
|
||||
def test_patch_openai_cli_request_for_codex_reorders_stable_prefix_keys() -> None:
|
||||
req = {
|
||||
"temperature": 0.7,
|
||||
"input": [],
|
||||
"metadata": {"request_id": "abc"},
|
||||
"model": "gpt-test",
|
||||
"tools": [{"type": "function", "name": "demo"}],
|
||||
"instructions": "keep",
|
||||
"store": True,
|
||||
"_aether_compact": True,
|
||||
}
|
||||
|
||||
out = patch_openai_cli_request_for_codex(req)
|
||||
|
||||
assert list(out.keys()) == [
|
||||
"model",
|
||||
"instructions",
|
||||
"tools",
|
||||
"input",
|
||||
"temperature",
|
||||
"metadata",
|
||||
"store",
|
||||
]
|
||||
|
||||
|
||||
def test_patch_openai_cli_request_for_codex_does_not_inject_prompt_cache_key() -> None:
|
||||
req = {"model": "gpt-test", "input": [], "_aether_compact": True}
|
||||
|
||||
out = patch_openai_cli_request_for_codex(req)
|
||||
|
||||
assert out is not req
|
||||
assert "_aether_compact" not in out
|
||||
assert "prompt_cache_key" not in out
|
||||
|
||||
|
||||
def test_maybe_patch_request_for_codex_is_noop_for_non_codex() -> None:
|
||||
req = {"model": "gpt-test", "input": []}
|
||||
out = maybe_patch_request_for_codex(
|
||||
provider_type="custom",
|
||||
provider_api_format="openai:cli",
|
||||
request_body=req,
|
||||
)
|
||||
assert out is req
|
||||
|
||||
|
||||
def test_maybe_patch_request_for_codex_is_noop_for_non_openai_cli() -> None:
|
||||
req = {"model": "gpt-test", "input": []}
|
||||
out = maybe_patch_request_for_codex(
|
||||
provider_type="codex",
|
||||
provider_api_format="openai:chat",
|
||||
request_body=req,
|
||||
)
|
||||
assert out is req
|
||||
|
||||
|
||||
def test_maybe_patch_request_for_codex_patches_for_codex_openai_cli() -> None:
|
||||
req = {"model": "gpt-test", "input": [], "_aether_compact": True, "store": True}
|
||||
out = maybe_patch_request_for_codex(
|
||||
provider_type="codex",
|
||||
provider_api_format="openai:cli",
|
||||
request_body=req,
|
||||
)
|
||||
|
||||
assert out is not req
|
||||
assert out["store"] is True
|
||||
assert "_aether_compact" not in out
|
||||
assert "prompt_cache_key" not in out
|
||||
|
||||
|
||||
def test_maybe_patch_request_for_codex_patches_for_codex_openai_compact() -> None:
|
||||
req = {"model": "gpt-test", "input": [], "_aether_compact": True, "store": True}
|
||||
out = maybe_patch_request_for_codex(
|
||||
provider_type="codex",
|
||||
provider_api_format="openai:compact",
|
||||
request_body=req,
|
||||
)
|
||||
|
||||
assert out is not req
|
||||
assert out["store"] is True
|
||||
assert "_aether_compact" not in out
|
||||
assert "prompt_cache_key" not in out
|
||||
assert behavior.envelope is None
|
||||
assert behavior.same_format_variant is None
|
||||
assert behavior.cross_format_variant is None
|
||||
|
||||
|
||||
def test_openai_cli_normalizer_request_from_internal_codex_variant_preserves_store() -> None:
|
||||
@@ -151,14 +27,14 @@ def test_openai_cli_normalizer_request_from_internal_codex_variant_preserves_sto
|
||||
assert out["store"] is True
|
||||
|
||||
|
||||
def test_openai_cli_normalizer_request_from_internal_codex_variant_defaults_store_false() -> None:
|
||||
def test_openai_cli_normalizer_request_from_internal_codex_variant_does_not_inject_store() -> None:
|
||||
from src.core.api_format.conversion.normalizers.openai_cli import OpenAICliNormalizer
|
||||
|
||||
normalizer = OpenAICliNormalizer()
|
||||
internal = normalizer.request_to_internal({"model": "gpt-test", "input": []})
|
||||
out = normalizer.request_from_internal(internal, target_variant="codex")
|
||||
|
||||
assert out["store"] is False
|
||||
assert "store" not in out
|
||||
|
||||
|
||||
def test_openai_cli_normalizer_codex_variant_keeps_instructions_missing_for_default_rule() -> None:
|
||||
@@ -176,7 +52,7 @@ def test_openai_cli_normalizer_codex_variant_keeps_instructions_missing_for_defa
|
||||
assert patched["instructions"] == "You are GPT-5."
|
||||
|
||||
|
||||
def test_openai_cli_normalizer_patch_for_codex_reorders_stable_prefix_keys() -> None:
|
||||
def test_openai_cli_normalizer_patch_for_codex_is_noop() -> None:
|
||||
from src.core.api_format.conversion.normalizers.openai_cli import OpenAICliNormalizer
|
||||
|
||||
normalizer = OpenAICliNormalizer()
|
||||
@@ -188,114 +64,14 @@ def test_openai_cli_normalizer_patch_for_codex_reorders_stable_prefix_keys() ->
|
||||
"model": "gpt-test",
|
||||
"tools": [{"type": "function", "name": "demo"}],
|
||||
"instructions": "keep",
|
||||
"_aether_compact": True,
|
||||
},
|
||||
"codex",
|
||||
)
|
||||
|
||||
assert out is not None
|
||||
assert list(out.keys()) == [
|
||||
"model",
|
||||
"instructions",
|
||||
"tools",
|
||||
"input",
|
||||
"temperature",
|
||||
"metadata",
|
||||
]
|
||||
|
||||
|
||||
def test_codex_envelope_extra_headers_does_not_inject_synthetic_headers() -> None:
|
||||
from src.services.provider.adapters.codex.envelope import codex_oauth_envelope
|
||||
|
||||
assert codex_oauth_envelope.extra_headers() is None
|
||||
|
||||
|
||||
def test_codex_envelope_wrap_request_injects_stable_prompt_cache_key_from_user_api_key() -> None:
|
||||
from src.services.provider.adapters.codex.envelope import codex_oauth_envelope
|
||||
|
||||
try:
|
||||
codex_oauth_envelope.prepare_context(
|
||||
provider_config=None,
|
||||
key_id="provider-key-123",
|
||||
user_api_key_id="user-key-123",
|
||||
is_stream=True,
|
||||
)
|
||||
out, url_model = codex_oauth_envelope.wrap_request(
|
||||
{"model": "gpt-test", "input": []},
|
||||
model="gpt-test",
|
||||
url_model=None,
|
||||
decrypted_auth_config=None,
|
||||
)
|
||||
finally:
|
||||
set_codex_request_context(None)
|
||||
|
||||
assert url_model is None
|
||||
assert "prompt_cache_key" not in out
|
||||
|
||||
|
||||
def test_codex_envelope_wrap_request_same_user_different_provider_keys_do_not_mutate_prompt_cache_key() -> (
|
||||
None
|
||||
):
|
||||
from src.services.provider.adapters.codex.envelope import codex_oauth_envelope
|
||||
|
||||
try:
|
||||
codex_oauth_envelope.prepare_context(
|
||||
provider_config=None,
|
||||
key_id="provider-key-123",
|
||||
user_api_key_id="user-key-123",
|
||||
is_stream=True,
|
||||
)
|
||||
out_a, _ = codex_oauth_envelope.wrap_request(
|
||||
{"model": "gpt-test", "input": []},
|
||||
model="gpt-test",
|
||||
url_model=None,
|
||||
decrypted_auth_config=None,
|
||||
)
|
||||
codex_oauth_envelope.prepare_context(
|
||||
provider_config=None,
|
||||
key_id="provider-key-456",
|
||||
user_api_key_id="user-key-123",
|
||||
is_stream=True,
|
||||
)
|
||||
out_b, _ = codex_oauth_envelope.wrap_request(
|
||||
{"model": "gpt-test", "input": []},
|
||||
model="gpt-test",
|
||||
url_model=None,
|
||||
decrypted_auth_config=None,
|
||||
)
|
||||
finally:
|
||||
set_codex_request_context(None)
|
||||
|
||||
assert "prompt_cache_key" not in out_a
|
||||
assert "prompt_cache_key" not in out_b
|
||||
|
||||
|
||||
def test_codex_envelope_wrap_request_compact_does_not_inject_prompt_cache_key() -> None:
|
||||
from src.services.provider.adapters.codex.envelope import codex_oauth_envelope
|
||||
|
||||
try:
|
||||
codex_oauth_envelope.prepare_context(
|
||||
provider_config=None,
|
||||
key_id="provider-key-123",
|
||||
user_api_key_id="user-key-123",
|
||||
is_stream=False,
|
||||
)
|
||||
out, _ = codex_oauth_envelope.wrap_request(
|
||||
{"model": "gpt-test", "input": [], "_aether_compact": True},
|
||||
model="gpt-test",
|
||||
url_model=None,
|
||||
decrypted_auth_config=None,
|
||||
)
|
||||
finally:
|
||||
set_codex_request_context(None)
|
||||
|
||||
assert "_aether_compact" not in out
|
||||
assert "prompt_cache_key" not in out
|
||||
assert out is None
|
||||
|
||||
|
||||
def test_codex_passthrough_builder_preserves_real_codex_headers() -> None:
|
||||
from src.services.provider.adapters.codex.envelope import codex_oauth_envelope
|
||||
|
||||
builder = PassthroughRequestBuilder()
|
||||
endpoint = SimpleNamespace(api_family="openai", endpoint_kind="cli", header_rules=None)
|
||||
key = SimpleNamespace(api_key="unused")
|
||||
@@ -314,7 +90,6 @@ def test_codex_passthrough_builder_preserves_real_codex_headers() -> None:
|
||||
endpoint=endpoint,
|
||||
key=key,
|
||||
pre_computed_auth=("Authorization", "Bearer upstream-token"),
|
||||
envelope=cast(ProviderEnvelope, codex_oauth_envelope),
|
||||
)
|
||||
|
||||
assert headers["accept"] == "text/event-stream"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from src.services.provider.adapters.codex.context import (
|
||||
CodexRequestContext,
|
||||
set_codex_request_context,
|
||||
)
|
||||
from src.services.provider.prompt_cache import (
|
||||
build_stable_codex_prompt_cache_key,
|
||||
build_stable_openai_prompt_cache_key,
|
||||
@@ -103,7 +107,7 @@ def test_maybe_patch_request_with_prompt_cache_key_for_codex_openai_cli() -> Non
|
||||
|
||||
|
||||
def test_maybe_patch_request_with_prompt_cache_key_skips_official_compact() -> None:
|
||||
req = {"model": "gpt-5", "input": [], "_aether_compact": True}
|
||||
req = {"model": "gpt-5", "input": []}
|
||||
|
||||
out = maybe_patch_request_with_prompt_cache_key(
|
||||
req,
|
||||
@@ -117,16 +121,20 @@ def test_maybe_patch_request_with_prompt_cache_key_skips_official_compact() -> N
|
||||
assert "prompt_cache_key" not in out
|
||||
|
||||
|
||||
def test_maybe_patch_request_with_prompt_cache_key_skips_codex_compact_marker() -> None:
|
||||
req = {"model": "gpt-5", "input": [], "_aether_compact": True}
|
||||
def test_maybe_patch_request_with_prompt_cache_key_skips_legacy_codex_compact_context() -> None:
|
||||
req = {"model": "gpt-5", "input": []}
|
||||
|
||||
out = maybe_patch_request_with_prompt_cache_key(
|
||||
req,
|
||||
provider_api_format="openai:cli",
|
||||
provider_type="codex",
|
||||
base_url="https://chatgpt.com/backend-api/codex",
|
||||
user_api_key_id="user-key-123",
|
||||
)
|
||||
try:
|
||||
set_codex_request_context(CodexRequestContext(is_compact=True))
|
||||
out = maybe_patch_request_with_prompt_cache_key(
|
||||
req,
|
||||
provider_api_format="openai:cli",
|
||||
provider_type="codex",
|
||||
base_url="https://chatgpt.com/backend-api/codex",
|
||||
user_api_key_id="user-key-123",
|
||||
)
|
||||
finally:
|
||||
set_codex_request_context(None)
|
||||
|
||||
assert out is req
|
||||
assert "prompt_cache_key" not in out
|
||||
|
||||
Reference in New Issue
Block a user