feat(providers): support Codex fast mode

This commit is contained in:
chengyongru
2026-07-21 17:55:17 +08:00
committed by chengyongru
parent b46e7f4377
commit 1d7bad3909
4 changed files with 59 additions and 0 deletions
+19
View File
@@ -676,6 +676,25 @@ Then run:
nanobot agent -m "Hello!"
```
To opt in to Codex Fast mode, merge this provider setting into `config.json`:
```json
{
"providers": {
"openaiCodex": {
"extraBody": {
"service_tier": "priority"
}
}
}
}
```
`priority` is the Responses API request value used by Codex Fast mode. The setting only works
for models and accounts that support Fast mode; remove `service_tier` to return to standard
processing. Fast mode consumes Codex credits at a higher rate. See the
[OpenAI Codex rate card](https://help.openai.com/en/articles/20001106) for current details.
For proxy, remote/headless login, model-name, or config-key errors, see [`troubleshooting.md`](./troubleshooting.md#provider-and-model-problems).
</details>
+1
View File
@@ -88,6 +88,7 @@ def _make_provider_core(
provider = OpenAICodexProvider(
default_model=model,
proxy=getattr(p, "proxy", None) if p else None,
extra_body=p.extra_body if p else None,
)
elif backend == "azure_openai":
from nanobot.providers.azure_openai_provider import AzureOpenAIProvider
@@ -37,10 +37,12 @@ class OpenAICodexProvider(LLMProvider):
self,
default_model: str = "openai-codex/gpt-5.6-sol",
proxy: str | None = None,
extra_body: dict[str, Any] | None = None,
):
super().__init__(api_key=None, api_base=None)
self.default_model = default_model
self.proxy = proxy or None
self._extra_body = dict(extra_body or {})
async def _call_codex(
self,
@@ -74,6 +76,9 @@ class OpenAICodexProvider(LLMProvider):
body["reasoning"] = reasoning_options
if tools:
body["tools"] = convert_tools(tools)
if self._extra_body:
# Apply explicit provider overrides last, matching other provider backends.
body.update(self._extra_body)
stage = "oauth_token"
try:
@@ -9,6 +9,8 @@ import pytest
from loguru import logger
import nanobot.providers.base as provider_base
from nanobot.config.schema import Config
from nanobot.providers.factory import make_provider
from nanobot.providers.openai_codex_provider import (
OpenAICodexProvider,
_build_reasoning_options,
@@ -220,6 +222,38 @@ async def test_codex_prompt_cache_key_uses_stable_conversation_prefix(monkeypatc
assert bodies[0]["prompt_cache_key"] == bodies[1]["prompt_cache_key"]
assert bodies[0]["prompt_cache_key"] != bodies[2]["prompt_cache_key"]
assert all("service_tier" not in body for body in bodies)
@pytest.mark.asyncio
async def test_codex_provider_applies_extra_body_from_config(monkeypatch) -> None:
bodies: list[dict[str, Any]] = []
_mock_codex_token(monkeypatch)
async def fake_request(_url, _headers, body, **_kwargs):
bodies.append(body)
return "ok", [], "stop", {}, None
monkeypatch.setattr("nanobot.providers.openai_codex_provider._request_codex", fake_request)
config = Config.model_validate({
"agents": {
"defaults": {
"model": "openai-codex/gpt-5.6-sol",
"provider": "openai_codex",
},
},
"providers": {
"openaiCodex": {
"extraBody": {"service_tier": "priority"},
},
},
})
provider = make_provider(config)
response = await provider.chat([{"role": "user", "content": "hello"}])
assert response.content == "ok"
assert bodies[0]["service_tier"] == "priority"
@pytest.mark.asyncio