core/config: default OpenAI provider_tools to web_search

Omitted provider_tools enables web_search; use [] to disable hosted tools.
This commit is contained in:
2026-07-15 21:43:39 +08:00
parent 84a83e0485
commit 074a3313ce
5 changed files with 17 additions and 3 deletions
+1 -1
View File
@@ -57,7 +57,7 @@ Async SQLAlchemy + aiosqlite. `MemoryStore`: schema init (+ lightweight SQLite `
- **`ChatClient`** Protocol for `chat_completions` (agent history stays chat-shaped).
- **OpenAI Responses integration**: `ResponsesChatClient` adapts platform `OpenAIClient.responses` to `ChatClient`; selected automatically for `OpenAIProvider` in `create_client`. Compat/DeepSeek stay on chat completions.
- **Provider-side tools**: `OpenAIProvider.provider_tools` (list of dicts, e.g. `{type="web_search"}`) merged into Responses `tools` alongside local function tools; never executed by `ToolRegistry`.
- **Provider-side tools**: `OpenAIProvider.provider_tools` (list of dicts; default `[{type="web_search"}]` when omitted; `[]` disables) merged into Responses `tools` alongside local function tools; never executed by `ToolRegistry`.
- **`@tool` / `ToolRegistry`**: decorator infers JSON Schema from type hints; execute tools by name.
- **`run_chat_loop`**: multi-round tool loop; default **streaming** text deltas + stream tool-call merge; parallel tools; tool-result char budget; soft context compact on request (**API-calibrated** after first usage when available); cooperative cancel points; optional `on_limit`.
- **`ChatAgent`**: optional `MemoryStore` (user message persisted immediately; **completed tool batches checkpointed** mid-turn; unfinished assistant suffix rolled back on failure); `stream`; system prompt; `retry()` continues incomplete turns (user-only **or** after committed tools — does not re-run those tools).
+1
View File
@@ -39,6 +39,7 @@ access_key_or_token = "sk-replace-me"
# access_key_or_token = "sk-replace-me"
# url = "https://api.openai.com/v1"
# # Hosted/provider-side tools (OpenAI runs them; not local ToolRegistry).
# # Default if omitted: [{ type = "web_search" }]. Use [] to disable.
# # Examples: web_search, file_search (+ vector_store_ids), code_interpreter, mcp.
# provider_tools = [
# { type = "web_search" },
+8 -1
View File
@@ -62,6 +62,11 @@ def _default_openai_models() -> dict[str, ModelConfig]:
}
def _default_openai_provider_tools() -> list[dict[str, Any]]:
"""Hosted tools when TOML omits ``provider_tools``."""
return [{"type": "web_search"}]
class OpenAIProvider(ProviderConfig, tag="openai"):
"""OpenAI platform provider (agent uses Responses API).
@@ -71,10 +76,12 @@ class OpenAIProvider(ProviderConfig, tag="openai"):
When ``models`` is omitted in TOML, seeds a small default catalog (same idea
as DeepSeek). Explicit ``models = {}`` stays empty (recoverable / free-form).
When ``provider_tools`` is omitted, defaults to web_search; use
``provider_tools = []`` to disable hosted tools.
"""
models: dict[str, ModelConfig] = field(default_factory=_default_openai_models)
provider_tools: list[dict[str, Any]] = field(default_factory=list)
provider_tools: list[dict[str, Any]] = field(default_factory=_default_openai_provider_tools)
class OpenAICompatibleProvider(ProviderConfig, tag="openai-compatible"):
+6
View File
@@ -61,6 +61,12 @@ def test_deepseek_default_models_on_construct() -> None:
def test_openai_default_models_on_construct() -> None:
provider = OpenAIProvider(access_key_or_token="sk-test")
assert set(provider.models) == {"gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano"}
assert provider.provider_tools == [{"type": "web_search"}]
def test_openai_explicit_empty_provider_tools() -> None:
provider = OpenAIProvider(access_key_or_token="sk-test", provider_tools=[])
assert provider.provider_tools == []
def test_openai_omitted_preset_and_models_from_toml(tmp_path: Path) -> None:
+1 -1
View File
@@ -24,7 +24,7 @@ def test_openai_provider_defaults_base_url() -> None:
client = create_client(provider)
assert isinstance(client, ResponsesChatClient)
assert hasattr(client, "chat_completions")
assert client._provider_tools == []
assert client._provider_tools == [{"type": "web_search"}]
def test_openai_provider_tools_passed_to_wrapper() -> None: