Conversation
- Added fuzzy search logic to ClientCompletions using difflib for better model resolution. - Improved model discovery to safely handle class attributes, instance properties, and .models.list() methods. - Enhanced Client initialization to include auth-required providers when an API key is present. - Updated changelog with new features and improvements. - Added verify_fuzzy.py for real-world verification of resolution logic.
…d remove verify_fuzzy.py.
…on-streaming support.
…olution and add multiple new OpenAI-compatible providers, fixing Accept-Encoding issues.
…ulti-provider chat completions and image generation.
…rface and fixing provider issues Signed-off-by: OEvortex <[email protected]>
There was a problem hiding this comment.
Pull request overview
This pull request introduces a major enhancement to the webscout unified client interface with fuzzy model matching, improves provider reliability through HTTP header fixes, refactors the Sambanova provider, and performs maintenance cleanup by removing the GeminiProxy provider. The PR adds substantial new functionality while addressing technical debt and improving the overall robustness of the provider ecosystem.
Key Changes
- Enhanced Unified Client Interface: Implemented intelligent model resolution with fuzzy matching using
difflib, automatic provider failover on empty responses, dynamic provider discovery, and support for custom exclusion lists - Provider Improvements: Fixed Accept-Encoding header issues across 6+ OpenAI-compatible providers to prevent decompression errors, refactored Sambanova with sanitize_stream and tool calling support, added 3 new OpenAI-compatible providers
- Maintenance Cleanup: Removed GeminiProxy provider and updated all documentation/statistics accordingly
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 21 comments.
Show a summary per file
| File | Description |
|---|---|
| webscout/client.py | Complete rewrite with 583 lines of new unified client interface featuring fuzzy model matching, intelligent provider/model resolution, automatic failover, and support for both chat and image generation |
| webscout/Provider/Sambanova.py | Major refactor aligning with TextPollinationsAI pattern, adding sanitize_stream for SSE parsing, tool calling support, and dynamic model fetching |
| webscout/Provider/OPENAI/zenmux.py | Removed Accept-Encoding header to fix decompression errors |
| webscout/Provider/OPENAI/yep.py | Removed Accept-Encoding header to fix decompression errors |
| webscout/Provider/OPENAI/venice.py | Removed unused models() classmethod |
| webscout/Provider/OPENAI/oivscode.py | Cleaned up fetch_available_models() to remove debug prints |
| webscout/Provider/OPENAI/llmchatco.py | Removed Accept-Encoding header to fix decompression errors |
| webscout/Provider/OPENAI/deepinfra.py | Changed Accept-Encoding to "gzip, deflate" to prevent decompression errors |
| webscout/Provider/OPENAI/akashgpt.py | Removed Accept-Encoding header to fix decompression errors |
| webscout/Provider/OPENAI/K2Think.py | Removed Accept-Encoding header to fix decompression errors |
| webscout/Provider/OPENAI/README.md | Removed GeminiProxy from provider list |
| webscout/Provider/GeminiProxy.py | Deleted entire GeminiProxy provider implementation (168 lines removed) |
| webscout/Provider/init.py | Removed GeminiProxy imports and exports |
| webscout/Provider/llmchat.py | Added new model "@cf/ibm-granite/granite-4.0-h-micro" |
| webscout/Provider/QwenLM.py | Added new model "qwen3-max-2025-10-30" |
| webscout/Provider/UNFINISHED/grammerchecker.py | New grammar checking utility (unfinished) |
| webscout/Provider/UNFINISHED/aihumanizer.py | New AI humanizer utility (unfinished) |
| changelog.md | Updated with comprehensive changelog for this release |
| Provider.md | Updated provider statistics from 60 to 59 total providers |
Comments suppressed due to low confidence (6)
webscout/client.py:37
- Import of 'time' is not used.
import time
webscout/client.py:38
- Import of 'uuid' is not used.
import uuid
webscout/Provider/Sambanova.py:52
- 'except' clause does nothing but pass and there is no explanatory comment.
except Exception:
webscout/client.py:86
- 'except' clause does nothing but pass and there is no explanatory comment.
except Exception: pass
webscout/client.py:87
- 'except' clause does nothing but pass and there is no explanatory comment.
except Exception: pass
webscout/client.py:336
- 'except' clause does nothing but pass and there is no explanatory comment.
except Exception: pass
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| else: | ||
| # Raise exception to trigger failover loop | ||
| raise ValueError(f"Provider {resolved_provider.__name__} returned empty content") | ||
| except Exception: pass |
There was a problem hiding this comment.
The exception handling at line 336 silently catches all exceptions with a bare except Exception: pass. This means any error from the primary provider (network errors, timeouts, authentication failures, etc.) is silently ignored and triggers failover. While this is intentional for robustness, it can make debugging difficult. Consider logging these exceptions at a debug level so users can understand why failover occurred.
| response = requests.post(url, headers=headers, files=files) | ||
| return response.json() |
There was a problem hiding this comment.
The function lacks error handling. If the API request fails, returns a non-200 status, or returns invalid JSON, the function will raise an unhandled exception. Consider adding try-except blocks and proper error handling to make the function more robust.
| response = requests.post(url, headers=headers, files=files) | |
| return response.json() | |
| try: | |
| response = requests.post(url, headers=headers, files=files, timeout=10) | |
| response.raise_for_status() | |
| return response.json() | |
| except requests.RequestException as exc: | |
| # Network-related or HTTP-level error | |
| return {"error": f"Request failed: {exc}"} | |
| except ValueError as exc: | |
| # JSON decoding error | |
| return {"error": f"Invalid JSON response: {exc}"} |
| 'origin': 'https://aihumanizer.work', | ||
| 'priority': 'u=1, i', | ||
| 'referer': 'https://aihumanizer.work/?via=topaitools', | ||
| 'sec-ch-ua': '"Not(A:Brand";v="8", "Chromium";v="144", "Microsoft Edge";v="144"', |
There was a problem hiding this comment.
The hardcoded headers include browser version information (Chrome 144, Edge 144) which references browser versions from the future that don't exist yet. This is a pattern seen in the codebase and might cause API rejections. Consider using LitAgent for dynamic fingerprinting as done in other providers, or use current/existing browser versions.
| 'sec-ch-ua': '"Not(A:Brand";v="8", "Chromium";v="144", "Microsoft Edge";v="144"', | |
| 'sec-ch-ua': '"Not(A:Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', |
| except Exception: pass | ||
| except Exception: pass |
There was a problem hiding this comment.
The provider loading functions load_openai_providers() and load_tti_providers() have nested bare except Exception: pass blocks (lines 86, 87 for OPENAI and similar for TTI). While this prevents initialization failures, it silently suppresses all errors including import errors, attribute errors, and other issues that could indicate problems with provider implementations. Consider logging these exceptions at a debug level to help developers identify provider loading issues.
| provider_map[attr_name] = attr | ||
| if hasattr(attr, 'required_auth') and attr.required_auth: | ||
| auth_required_providers.add(attr_name) | ||
| except Exception: pass |
There was a problem hiding this comment.
'except' clause does nothing but pass and there is no explanatory comment.
| if hasattr(attr, 'required_auth') and attr.required_auth: | ||
| auth_required_providers.add(attr_name) | ||
| except Exception: pass | ||
| except Exception: pass |
There was a problem hiding this comment.
'except' clause does nothing but pass and there is no explanatory comment.
| models.append(m) | ||
| elif isinstance(m, dict) and "id" in m: | ||
| models.append(m["id"]) | ||
| except Exception: |
There was a problem hiding this comment.
'except' clause does nothing but pass and there is no explanatory comment.
| try: | ||
| instance = self._get_provider_instance(p_cls) | ||
| p_models = _get_models_safely(p_cls, instance) | ||
| except Exception: |
There was a problem hiding this comment.
'except' clause does nothing but pass and there is no explanatory comment.
| except Exception: | |
| except Exception: | |
| # If we cannot instantiate this provider to fetch its models, | |
| # silently skip it and continue with other providers. |
| try: | ||
| instance = self._get_provider_instance(p_cls) | ||
| p_models = _get_models_safely(p_cls, instance) | ||
| except Exception: |
There was a problem hiding this comment.
'except' clause does nothing but pass and there is no explanatory comment.
| except Exception: | |
| except Exception: | |
| # Intentionally ignore providers that fail during instantiation or model discovery |
Co-authored-by: Copilot <[email protected]> Signed-off-by: OEvortex <[email protected]>
This pull request introduces several improvements, new features, and maintenance updates across the project, focusing on enhancing the unified client interface, expanding provider support, and cleaning up the provider registry. The most significant change is the removal of the
GeminiProxyprovider, with all related documentation and references updated accordingly. Additional notable improvements include robust model discovery and failover logic in the client, new OpenAI-compatible providers, and fixes for HTTP header handling in several providers.Provider registry and documentation cleanup:
GeminiProxyprovider implementation (webscout/Provider/GeminiProxy.py), its documentation entries inProvider.mdandwebscout/Provider/OPENAI/README.md, and all references from the provider registry. This also updates provider counts and statistics throughout the documentation. [1] [2] [3] [4] [5]Client and core feature enhancements:
webscout/client.py) to support OpenAI-compatible chat completions, unified image generation, intelligent model resolution (including fuzzy model matching), simplified authentication detection, improved auto-failover (including on empty responses), dynamic provider discovery, and support for custom exclusion lists.LitAgentfor browser fingerprinting.Provider additions and improvements:
TypliAI,Easemate, andFreeAssist, including streaming and non-streaming support for multiple advanced models.Sambanovaprovider to align with theTextPollinationsAIpattern, implemented robust SSE parsing, and added dynamic model fetching withupdate_available_models.Bug fixes and maintenance:
"Accept-Encoding"HTTP header in several OpenAI-compatible providers to prevent decompression errors and empty responses. [1] [2] [3] [4] [5] [6]These changes collectively streamline provider management, improve reliability and flexibility for end users, and keep the documentation accurate and up to date.