From 51d2b7549f0c7af53e48b648644b19b6b0e85033 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Sat, 6 Jun 2026 16:27:03 +0545 Subject: [PATCH] feat(devgen/providers):improve provider error handling and response parsing --- devgen/providers/__init__.py | 24 ------------------------ devgen/providers/anthropic.py | 5 ++++- devgen/providers/gemini.py | 5 ++++- devgen/providers/huggingface.py | 32 +++++++++++++++++++++++++++----- devgen/providers/openai.py | 27 +++++++++++++++++++++------ devgen/providers/openrouter.py | 10 ++++++++-- 6 files changed, 64 insertions(+), 39 deletions(-) diff --git a/devgen/providers/__init__.py b/devgen/providers/__init__.py index ee5f5de..e69de29 100644 --- a/devgen/providers/__init__.py +++ b/devgen/providers/__init__.py @@ -1,24 +0,0 @@ -def get_provider(name): - name_lower = name.lower() - if name_lower == "gemini": - from devgen.providers.gemini import GeminiProvider - - return GeminiProvider() - elif name_lower == "openai": - from devgen.providers.openai import OpenaiProvider - - return OpenaiProvider() - elif name_lower == "huggingface": - from devgen.providers.huggingface import HuggingfaceProvider - - return HuggingfaceProvider() - elif name_lower == "openrouter": - from devgen.providers.openrouter import OpenrouterProvider - - return OpenrouterProvider() - elif name_lower == "anthropic": - from devgen.providers.anthropic import AnthropicProvider - - return AnthropicProvider() - - raise NotImplementedError(f"Provider '{name}' is not implemented yet.") diff --git a/devgen/providers/anthropic.py b/devgen/providers/anthropic.py index 79b04b4..f9174bb 100644 --- a/devgen/providers/anthropic.py +++ b/devgen/providers/anthropic.py @@ -9,7 +9,10 @@ class AnthropicProvider: ) -> str: """Generates a response using the Anthropic API.""" if not api_key: - raise ValueError("Anthropic API key is required.") + raise ValueError( + "Anthropic API key is missing. " + "Set it via `devgen setup config` or pass --api-key." + ) try: client = anthropic.Anthropic(api_key=api_key) diff --git a/devgen/providers/gemini.py b/devgen/providers/gemini.py index 11fef68..8ceafc8 100644 --- a/devgen/providers/gemini.py +++ b/devgen/providers/gemini.py @@ -15,7 +15,10 @@ class GeminiProvider: recommended model. """ if not api_key: - raise ValueError("Gemini API key is required.") + raise ValueError( + "Gemini API key is missing. " + "Set it via `devgen setup config` or pass --api-key." + ) client = genai.Client(api_key=api_key) diff --git a/devgen/providers/huggingface.py b/devgen/providers/huggingface.py index d72033c..221a34e 100644 --- a/devgen/providers/huggingface.py +++ b/devgen/providers/huggingface.py @@ -15,7 +15,10 @@ class HuggingfaceProvider: ) -> str: """Generates a response using Hugging Face API.""" if not api_key: - raise ValueError("Hugging Face API token is required.") + raise ValueError( + "Hugging Face API token is missing. " + "Set it via `devgen setup config` or pass --api-key." + ) api_url = self.API_URL_TEMPLATE.format(model=model) headers = {"Authorization": f"Bearer {api_key}"} @@ -34,12 +37,31 @@ class HuggingfaceProvider: response.raise_for_status() result = response.json() - if isinstance(result, list) and "generated_text" in result[0]: + if isinstance(result, list) and result and "generated_text" in result[0]: return result[0]["generated_text"].strip() elif isinstance(result, dict) and "error" in result: - raise RuntimeError(f"Hugging Face API error: {result['error']}") + err = result["error"] + if "is currently loading" in str(err).lower(): + raise RuntimeError( + f"Hugging Face model is loading: {err}. " + "Wait a minute and retry, or pick a different model." + ) + raise RuntimeError(f"Hugging Face API error: {err}") else: - return str(result) + raise RuntimeError( + "Hugging Face returned an unexpected response shape. " + "The model may not support text-generation." + ) + except requests.HTTPError as e: + status = e.response.status_code if e.response is not None else "?" + raise RuntimeError( + f"Hugging Face request failed (HTTP {status}): {e}. " + "Check the model id and your token permissions." + ) from e + except requests.RequestException as e: + raise RuntimeError( + f"Hugging Face network error: {e}. Check your connection." + ) from e except Exception as e: - raise RuntimeError(f"Hugging Face generation failed: {e}") + raise RuntimeError(f"Hugging Face generation failed: {e}") from e diff --git a/devgen/providers/openai.py b/devgen/providers/openai.py index c64763f..d3cd3ff 100644 --- a/devgen/providers/openai.py +++ b/devgen/providers/openai.py @@ -32,20 +32,35 @@ class OpenaiProvider: Returns: str: Generated response content. """ + if not api_key: + raise ValueError( + "OpenAI API key is missing. " + "Set it via `devgen setup config` or pass --api-key." + ) + # 1. Create a client instance with the API key. try: client = OpenAI(api_key=api_key) except Exception as e: # Add error handling if the client fails to initialize - raise RuntimeError(f"Failed to initialize OpenAI client: {e}") + raise RuntimeError( + f"Failed to initialize OpenAI client: {e}. " + "Verify the key is valid and that the `openai` package is installed." + ) from e # Remove debug from kwargs if present kwargs.pop("debug", None) # 2. Use the modern API syntax: client.chat.completions.create - response = client.chat.completions.create( - model=model or self.DEFAULT_MODEL, - messages=[{"role": "user", "content": prompt}], - **kwargs, - ) + try: + response = client.chat.completions.create( + model=model or self.DEFAULT_MODEL, + messages=[{"role": "user", "content": prompt}], + **kwargs, + ) + except Exception as e: + raise RuntimeError( + f"OpenAI request failed: {e}. " + "Check the model name, API key permissions, and your account quota." + ) from e return response.choices[0].message.content.strip() diff --git a/devgen/providers/openrouter.py b/devgen/providers/openrouter.py index 7f14b2d..5b9355c 100644 --- a/devgen/providers/openrouter.py +++ b/devgen/providers/openrouter.py @@ -11,7 +11,10 @@ class OpenrouterProvider: ) -> str: """Generates a response using OpenRouter.""" if not api_key: - raise ValueError("OpenRouter API key is required.") + raise ValueError( + "OpenRouter API key is missing. " + "Set it via `devgen setup config` or pass --api-key." + ) try: client = OpenAI( @@ -33,4 +36,7 @@ class OpenrouterProvider: ) return response.choices[0].message.content.strip() except Exception as e: - raise RuntimeError(f"OpenRouter generation failed: {e}") + raise RuntimeError( + f"OpenRouter request failed: {e}. " + "Verify the model id (e.g. `openai/gpt-4o`) and your API key credits." + ) from e