diff --git a/CHANGELOG.md b/CHANGELOG.md index b3d3d574..d5d06d07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ ## [Unreleased] +### 新增 +- ChatGPT/Codex 基础模型列表新增 GPT-5.6 Sol、Terra 和 Luna + +### 修复 +- 修复 ChatGPT/Codex 提供商连通性测试因 Responses API 参数不兼容而失败的问题 + ## [0.9.14] - 2026-07-25 ### 新增 diff --git a/src/octop/infra/agents/providers/presets.py b/src/octop/infra/agents/providers/presets.py index a1c49567..06c5d2f4 100644 --- a/src/octop/infra/agents/providers/presets.py +++ b/src/octop/infra/agents/providers/presets.py @@ -32,6 +32,24 @@ def load_provider_presets() -> list[dict[str, Any]]: "input": ["text"], }, {"id": "gpt-5.5", "name": "GPT-5.5", "enabled": True, "input": ["text"]}, + { + "id": "gpt-5.6-sol", + "name": "GPT-5.6 Sol", + "enabled": True, + "input": ["text"], + }, + { + "id": "gpt-5.6-terra", + "name": "GPT-5.6 Terra", + "enabled": True, + "input": ["text"], + }, + { + "id": "gpt-5.6-luna", + "name": "GPT-5.6 Luna", + "enabled": True, + "input": ["text"], + }, ], "logo_id": "openai", }, diff --git a/src/octop/infra/agents/providers/probe.py b/src/octop/infra/agents/providers/probe.py index 94b36e3f..944e6cfc 100644 --- a/src/octop/infra/agents/providers/probe.py +++ b/src/octop/infra/agents/providers/probe.py @@ -54,6 +54,9 @@ def build_probe_chat_model(row: Any, *, model_id: str | None = None) -> Any: "base_url": base_url, "api_key": row.api_key or "", "use_responses_api": True, + "store": False, + "streaming": True, + "output_version": "v0", } if headers: kwargs["default_headers"] = dict(headers) diff --git a/src/octop/infra/providers/codex_apply.py b/src/octop/infra/providers/codex_apply.py index 4ca64a41..51833d8a 100644 --- a/src/octop/infra/providers/codex_apply.py +++ b/src/octop/infra/providers/codex_apply.py @@ -19,6 +19,9 @@ {"id": "gpt-5.4", "name": "GPT-5.4", "enabled": True, "input": ["text"]}, {"id": "gpt-5.4-mini", "name": "GPT-5.4 mini", "enabled": True, "input": ["text"]}, {"id": "gpt-5.5", "name": "GPT-5.5", "enabled": True, "input": ["text"]}, + {"id": "gpt-5.6-sol", "name": "GPT-5.6 Sol", "enabled": True, "input": ["text"]}, + {"id": "gpt-5.6-terra", "name": "GPT-5.6 Terra", "enabled": True, "input": ["text"]}, + {"id": "gpt-5.6-luna", "name": "GPT-5.6 Luna", "enabled": True, "input": ["text"]}, ] diff --git a/tests/unit/providers/test_codex_oauth.py b/tests/unit/providers/test_codex_oauth.py index d0cf982d..45455cb9 100644 --- a/tests/unit/providers/test_codex_oauth.py +++ b/tests/unit/providers/test_codex_oauth.py @@ -97,3 +97,4 @@ def test_build_codex_headers_includes_account_id() -> None: def test_codex_provider_constants() -> None: assert CODEX_PROVIDER_NAME == "openai-codex" assert any(m["id"] == "gpt-5.4" for m in CODEX_MODELS) + assert {"gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"} <= {m["id"] for m in CODEX_MODELS} diff --git a/tests/unit/test_provider_preset_expansion.py b/tests/unit/test_provider_preset_expansion.py index 4a24ad0f..3aecdda0 100644 --- a/tests/unit/test_provider_preset_expansion.py +++ b/tests/unit/test_provider_preset_expansion.py @@ -39,6 +39,10 @@ def test_load_provider_presets_integration() -> None: gpt4o = next(m for m in openai["models"] if m["id"] == "gpt-4o") assert gpt4o.get("input") == ["text", "image"] + codex = next(p for p in presets if p["id"] == "openai-codex") + codex_ids = {m["id"] for m in codex["models"]} + assert {"gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"} <= codex_ids + kimi_cn = next(p for p in presets if p["id"] == "kimi-cn") kimi_k25 = next(m for m in kimi_cn["models"] if m["id"] == "kimi-k2.5") assert kimi_k25.get("input") == ["text", "image"] diff --git a/tests/unit/test_provider_probe.py b/tests/unit/test_provider_probe.py index 28c9d632..00502b96 100644 --- a/tests/unit/test_provider_probe.py +++ b/tests/unit/test_provider_probe.py @@ -26,3 +26,29 @@ def test_build_chat_model_includes_provider_id_and_model_name() -> None: assert provider.name == "HAI" assert model.id == "MiniMax-M2.7" assert model.name == "MiniMax-M2.7" + + +def test_build_chat_model_uses_codex_responses_compatibility_options() -> None: + row = SimpleNamespace( + name="Codex", + kind="openai", + base_url="https://chatgpt.com/backend-api/codex", + api_key="codex-token", + extra_json='{"headers": {"ChatGPT-Account-Id": "account-id"}}', + get_models=lambda: [{"id": "gpt-5.4", "name": "GPT-5.4"}], + ) + + with patch("langchain_openai.ChatOpenAI") as mock_chat_openai: + mock_chat_openai.return_value = object() + _build_chat_model(row, model_id="gpt-5.4") + + assert mock_chat_openai.call_args.kwargs == { + "model": "gpt-5.4", + "base_url": "https://chatgpt.com/backend-api/codex", + "api_key": "codex-token", + "use_responses_api": True, + "store": False, + "streaming": True, + "output_version": "v0", + "default_headers": {"ChatGPT-Account-Id": "account-id"}, + }