From a65485a1e52fc79739000426295a27d096f4c9d8 Mon Sep 17 00:00:00 2001 From: Fahad Date: Mon, 6 Oct 2025 22:36:44 +0400 Subject: [PATCH] feat: support for GPT-5-Pro highest reasoning model https://github.com/BeehiveInnovations/zen-mcp-server/issues/275 --- providers/openai_compatible.py | 14 +++++++++---- providers/openai_provider.py | 29 ++++++++++++++++++++++---- providers/shared/model_capabilities.py | 1 + server.py | 2 +- tests/test_openai_provider.py | 4 ++-- tools/apilookup.py | 4 ++-- 6 files changed, 41 insertions(+), 13 deletions(-) diff --git a/providers/openai_compatible.py b/providers/openai_compatible.py index ed580e6..4b514d7 100644 --- a/providers/openai_compatible.py +++ b/providers/openai_compatible.py @@ -391,9 +391,10 @@ class OpenAICompatibleProvider(ModelProvider): messages: list, temperature: float, max_output_tokens: Optional[int] = None, + capabilities: Optional[ModelCapabilities] = None, **kwargs, ) -> ModelResponse: - """Generate content using the /v1/responses endpoint for o3-pro via OpenAI library.""" + """Generate content using the /v1/responses endpoint for reasoning models.""" # Convert messages to the correct format for responses endpoint input_messages = [] @@ -412,10 +413,14 @@ class OpenAICompatibleProvider(ModelProvider): # Prepare completion parameters for responses endpoint # Based on OpenAI documentation, use nested reasoning object for responses endpoint + effort = "medium" + if capabilities and capabilities.default_reasoning_effort: + effort = capabilities.default_reasoning_effort + completion_params = { "model": model_name, "input": input_messages, - "reasoning": {"effort": "medium"}, # Use nested object for responses endpoint + "reasoning": {"effort": effort}, "store": True, } @@ -475,11 +480,11 @@ class OpenAICompatibleProvider(ModelProvider): operation=_attempt, max_attempts=max_retries, delays=retry_delays, - log_prefix="o3-pro responses endpoint", + log_prefix="responses endpoint", ) except Exception as exc: attempts = max(attempt_counter["value"], 1) - error_msg = f"o3-pro responses endpoint error after {attempts} attempt{'s' if attempts > 1 else ''}: {exc}" + error_msg = f"responses endpoint error after {attempts} attempt{'s' if attempts > 1 else ''}: {exc}" logging.error(error_msg) raise RuntimeError(error_msg) from exc @@ -614,6 +619,7 @@ class OpenAICompatibleProvider(ModelProvider): messages=messages, temperature=temperature, max_output_tokens=max_output_tokens, + capabilities=capabilities, **kwargs, ) diff --git a/providers/openai_provider.py b/providers/openai_provider.py index fedb7f5..d07b17b 100644 --- a/providers/openai_provider.py +++ b/providers/openai_provider.py @@ -31,7 +31,7 @@ class OpenAIModelProvider(OpenAICompatibleProvider): max_output_tokens=128_000, # 128K max output tokens supports_extended_thinking=True, # Supports reasoning tokens supports_system_prompts=True, - supports_streaming=True, + supports_streaming=False, supports_function_calling=True, supports_json_mode=True, supports_images=True, # GPT-5 supports vision @@ -41,6 +41,27 @@ class OpenAIModelProvider(OpenAICompatibleProvider): description="GPT-5 (400K context, 128K output) - Advanced model with reasoning support", aliases=["gpt5"], ), + "gpt-5-pro": ModelCapabilities( + provider=ProviderType.OPENAI, + model_name="gpt-5-pro", + friendly_name="OpenAI (GPT-5 Pro)", + intelligence_score=18, + use_openai_response_api=True, + context_window=400_000, + max_output_tokens=272_000, + supports_extended_thinking=True, + supports_system_prompts=True, + supports_streaming=False, + supports_function_calling=True, + supports_json_mode=True, + supports_images=True, + max_image_size_mb=20.0, + supports_temperature=True, + temperature_constraint=TemperatureConstraint.create("fixed"), + default_reasoning_effort="high", + description="GPT-5 Pro (400K context, 272K output) - Advanced model with reasoning support", + aliases=["gpt5pro"], + ), "gpt-5-mini": ModelCapabilities( provider=ProviderType.OPENAI, model_name="gpt-5-mini", @@ -50,7 +71,7 @@ class OpenAIModelProvider(OpenAICompatibleProvider): max_output_tokens=128_000, # 128K max output tokens supports_extended_thinking=True, # Supports reasoning tokens supports_system_prompts=True, - supports_streaming=True, + supports_streaming=False, supports_function_calling=True, supports_json_mode=True, supports_images=True, # GPT-5-mini supports vision @@ -284,7 +305,7 @@ class OpenAIModelProvider(OpenAICompatibleProvider): if category == ToolModelCategory.EXTENDED_REASONING: # Prefer models with extended thinking support # GPT-5-Codex first for coding tasks - preferred = find_first(["gpt-5-codex", "o3", "o3-pro", "gpt-5"]) + preferred = find_first(["gpt-5-codex", "gpt-5-pro", "o3", "o3-pro", "gpt-5"]) return preferred if preferred else allowed_models[0] elif category == ToolModelCategory.FAST_RESPONSE: @@ -296,5 +317,5 @@ class OpenAIModelProvider(OpenAICompatibleProvider): else: # BALANCED or default # Prefer balanced performance/cost models # Include GPT-5-Codex for coding workflows - preferred = find_first(["gpt-5", "gpt-5-codex", "gpt-5-mini", "o4-mini", "o3-mini"]) + preferred = find_first(["gpt-5", "gpt-5-codex", "gpt-5-pro", "gpt-5-mini", "o4-mini", "o3-mini"]) return preferred if preferred else allowed_models[0] diff --git a/providers/shared/model_capabilities.py b/providers/shared/model_capabilities.py index e3aa0a1..af01df1 100644 --- a/providers/shared/model_capabilities.py +++ b/providers/shared/model_capabilities.py @@ -51,6 +51,7 @@ class ModelCapabilities: supports_json_mode: bool = False supports_temperature: bool = True use_openai_response_api: bool = False + default_reasoning_effort: Optional[str] = None # Additional attributes max_image_size_mb: float = 0.0 diff --git a/server.py b/server.py index f2cdf4e..813c13d 100644 --- a/server.py +++ b/server.py @@ -49,7 +49,6 @@ from config import ( # noqa: E402 ) from tools import ( # noqa: E402 AnalyzeTool, - LookupTool, ChallengeTool, ChatTool, CLinkTool, @@ -58,6 +57,7 @@ from tools import ( # noqa: E402 DebugIssueTool, DocgenTool, ListModelsTool, + LookupTool, PlannerTool, PrecommitTool, RefactorTool, diff --git a/tests/test_openai_provider.py b/tests/test_openai_provider.py index 61cae0e..e03e3b1 100644 --- a/tests/test_openai_provider.py +++ b/tests/test_openai_provider.py @@ -126,7 +126,7 @@ class TestOpenAIProvider: assert capabilities.provider == ProviderType.OPENAI assert capabilities.supports_extended_thinking is True assert capabilities.supports_system_prompts is True - assert capabilities.supports_streaming is True + assert capabilities.supports_streaming is False assert capabilities.supports_function_calling is True assert capabilities.supports_temperature is True @@ -142,7 +142,7 @@ class TestOpenAIProvider: assert capabilities.provider == ProviderType.OPENAI assert capabilities.supports_extended_thinking is True assert capabilities.supports_system_prompts is True - assert capabilities.supports_streaming is True + assert capabilities.supports_streaming is False assert capabilities.supports_function_calling is True assert capabilities.supports_temperature is True diff --git a/tools/apilookup.py b/tools/apilookup.py index ba8273f..743b20d 100644 --- a/tools/apilookup.py +++ b/tools/apilookup.py @@ -40,7 +40,7 @@ SEARCH STRATEGY (MAXIMUM 2-4 SEARCHES TOTAL FOR THIS MISSION - THEN STOP): - IMPORTANT: Begin by determining today's date and current year - MANDATORY FOR OS-TIED APIS/SDKs: If the request involves iOS, macOS, Windows, Linux, Android, watchOS, tvOS, or any OS-specific framework/API: * FIRST perform a web search to determine "what is the latest [OS name] version [current year]" - * If the search is around a specific tool or an IDE, confirm the latest version "latest version [tool name]" + * If the search is around a specific tool or an IDE, confirm the latest version "latest version [tool name]" * DO NOT rely on your training data or knowledge cutoff for OS versions - you MUST search for current information * ONLY AFTER confirming the current OS version, search for APIs/SDKs/frameworks for that specific version * Example workflow: Search "latest iOS version [current year]" → Find current version → Then search "[current iOS version] SwiftUI glass effect button [current year]" @@ -87,7 +87,7 @@ class LookupTool(SimpleTool): def requires_model(self) -> bool: return False - def get_model_category(self) -> "ToolModelCategory": + def get_model_category(self) -> ToolModelCategory: from tools.models import ToolModelCategory return ToolModelCategory.FAST_RESPONSE