fix: key the routed vision-tool veto on is_routing_aggregator
The hand-rolled `_AGGREGATOR_MODEL_PREFIX_PROVIDERS = {"openrouter"}` duplicated
aggregator knowledge already owned by hermes_cli.providers.is_routing_aggregator,
so other vendor-prefixed aggregators (ai-gateway, kilocode, custom:* proxies)
kept bypassing the target-profile veto. Use the existing predicate instead of a
second frozenset.
Review finding: aggregator allowlist duplicated is_routing_aggregator and missed other vendor-prefixed aggregators.
This commit is contained in:
@@ -47,11 +47,6 @@ _ALIASES: dict[str, str] = {}
|
||||
_PROVIDER_LIST_CACHE: list[ProviderProfile] | None = None
|
||||
_discovered = False
|
||||
|
||||
# These APIs accept a ``vendor/model`` identifier while the request is sent to
|
||||
# the aggregator. A target provider can have stricter message-shape support
|
||||
# than the aggregator's generic OpenAI-compatible transport profile.
|
||||
_AGGREGATOR_MODEL_PREFIX_PROVIDERS = frozenset({"openrouter"})
|
||||
|
||||
# Repo-root ``plugins/model-providers/`` — populated at discovery time.
|
||||
_BUNDLED_PLUGINS_DIR = (
|
||||
Path(__file__).resolve().parent.parent / "plugins" / "model-providers"
|
||||
@@ -91,17 +86,21 @@ def get_provider_profile(name: str) -> ProviderProfile | None:
|
||||
def routed_model_rejects_vision_tool_messages(provider: str, model: str) -> bool:
|
||||
"""Whether an active route or its aggregator-targeted model rejects image tool parts.
|
||||
|
||||
``openrouter`` sends vendor-prefixed model IDs (for example,
|
||||
``xiaomi/mimo-v2.5``), but its own profile cannot describe every routed
|
||||
provider's tool-message compatibility. Preserve the transport profile as
|
||||
the default and consult a registered target profile only for known
|
||||
aggregators. Missing or unrecognized identities deliberately fail open.
|
||||
Routing aggregators such as ``openrouter`` send vendor-prefixed model IDs
|
||||
(for example, ``xiaomi/mimo-v2.5``), but their own profile cannot describe
|
||||
every routed provider's tool-message compatibility. Preserve the transport
|
||||
profile as the default and consult a registered target profile only for
|
||||
routing aggregators. Missing or unrecognized identities deliberately fail open.
|
||||
"""
|
||||
provider_name = str(provider or "").strip().lower()
|
||||
profile = get_provider_profile(provider_name)
|
||||
if profile is not None and profile.supports_vision_tool_messages is False:
|
||||
return True
|
||||
if provider_name not in _AGGREGATOR_MODEL_PREFIX_PROVIDERS:
|
||||
# Routing aggregators accept a ``vendor/model`` identifier while the request is sent
|
||||
# to the aggregator; the target provider can have stricter message-shape support than
|
||||
# the aggregator's generic OpenAI-compatible transport profile.
|
||||
from hermes_cli.providers import is_routing_aggregator
|
||||
if not is_routing_aggregator(provider_name):
|
||||
return False
|
||||
|
||||
target_name, separator, _ = str(model or "").strip().partition("/")
|
||||
|
||||
Reference in New Issue
Block a user