fix(provider): select anthropic base_url for dual-section named providers in sub-sessions (#11059) - #37705
Closed
rodboev wants to merge 3 commits into
Closed
Conversation
14 tasks
rodboev
force-pushed
the
pr/named-provider-anthropic-base-url
branch
from
June 28, 2026 16:31
3f07ed8 to
255d158
Compare
rodboev
force-pushed
the
pr/named-provider-anthropic-base-url
branch
from
June 28, 2026 20:00
d5b804d to
2ab861b
Compare
Contributor
Author
|
Withdrawing this in favor of #45842, which already landed with the overlapping Anthropic base URL fix. Closing to keep the queue clean. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Named custom providers with
api_mode: anthropic_messagesdon't strip trailing/vNsuffixes frombase_urlbefore handing it to the Anthropic SDK. The SDK appends its own/v1/messages, producing double-versioned paths like.../v4/v1/messagesor.../v1/v1/messagesthat 404.This bites cron and delegate sub-sessions that resolve a named provider carrying an OpenAI-wire base URL (e.g.
https://gateway.example.com/v4) while the transport isanthropic_messages.The azure-foundry branch (line 370) and opencode-zen/go branch (line 407) of
_resolve_runtime_from_pool_entryalready strip/v1foranthropic_messages, but the named custom provider path (_resolve_named_custom_runtime) and the bareprovider=customfallback were both missing the same guard.Repro findings
Root cause location:
hermes_cli/runtime_provider.py, function_resolve_named_custom_runtime(lines 726-734 before fix).Mechanism: The function correctly derives
api_modefrom the custom provider config or auto-detects it from the URL, but returnsbase_urlas-is without any version-suffix normalization. Whenapi_mode == "anthropic_messages", the Anthropic SDK appends/v1/messagesto the base URL, creating path doubling.Three code paths affected:
result["base_url"]was the raw config URL._try_resolve_from_custom_poolreturnsbase_urlunstripped; the caller didn't post-process it.provider=customfallback: both its pool result and direct return passedbase_urlthrough without stripping.The cron scheduler (
cron/scheduler.py:1565-1566) forwardsjob.get("base_url")asexplicit_base_url. When the job lacks a base_url, resolution falls to the provider config, which hits the named custom provider path. No changes needed incron/scheduler.py; the fix is entirely in the resolution function.Changes
hermes_cli/runtime_provider.py:Direct path (after line 726): Extract
api_modeinto a variable before building the result dict. Whenapi_mode == "anthropic_messages", applyre.sub(r"/v\d+/?$", "", base_url)to strip any trailing/vNsuffix.Pool path (after line 696): After
_try_resolve_from_custom_poolreturns, apply the same/vNstripping topool_result["base_url"]when the resolvedapi_modeisanthropic_messages.The regex
/v\d+/?$is intentionally broader than the existing/v1/?$pattern used in the azure-foundry branch, because named providers can carry arbitrary version suffixes (/v1,/v4, etc.) depending on the gateway configuration.tests/hermes_cli/test_runtime_provider_resolution.py(7 new tests):test_named_custom_provider_anthropic_strips_v1/v1stripped foranthropic_messagestest_named_custom_provider_anthropic_strips_v4/v4stripped foranthropic_messagestest_named_custom_provider_anthropic_no_strip_when_no_version_suffix/vNare untouchedtest_named_custom_provider_chat_completions_keeps_v1/v1preserved forchat_completionstest_named_custom_provider_anthropic_pool_strips_v1/v1test_named_custom_provider_anthropic_strips_v1_trailing_slash/v1/(trailing slash) strippedTest plan
test_runtime_provider_resolution.pypasstest_named_custom_provider_anthropic_api_modestill passes (its URLhttps://proxy.example.com/anthropichas no/vNsuffix)Validation
anthropic_messages, base_url.../v1.../v1/v1/messages(404).../v1/messagesanthropic_messages, base_url.../v4.../v4/v1/messages(404).../v1/messagesanthropic_messages, base_url.../anthropicchat_completions, base_url.../v1anthropic_messages, base_url.../v1.../v1/v1/messages(404).../v1/messagesCloses #11059.