Upstream moved the regression into the core package and added a
loopback-bind skip. Preserve that handling while keeping the bounded
readiness probes after successful listener startup.
The disconnect regression can attempt its first client connection before
its test listeners are reachable. Add a bounded TCP probe so the test
exercises disconnect cleanup instead of racing listener startup.
Hidden route tags select the provider only after child startup, while
clients that support exact model strings need the gateway-visible ID up
front. Publish the client-to-target mapping and accept either identity
through existing discovery resolution.
Provider imports exposed live context limits, but CCR discarded them and
fell back to stale static entries. Preserve physical and effective limits
so generated catalogs and model discovery advertise the provider-specific
usable window.
Bug evidence from request_logs.sqlite:
request body: {"model":"NebulaCoder/nebulacoder-cot-v8.0", ...}
response body: {"error":{"message":"All target providers failed.",
"attempts":[
{"provider":"openai","provider_name":"provider-nebulacoder-ee070b8656",
"stage":"model_resolution",
"message":"Model "NebulaCoder/nebulacoder-cot-v8.0" is not configured
for target provider openai.
Allowed models: nebulacoder-v8.0, nebulacoder-cot-v8.0."}
]}}
Root cause: prepareUpstreamCredentialAttempt has a !target branch that uses:
bodyHasConfiguredProviderModelSelector(input.attempt.body, input.config)
? input.attempt.body ← original body with "NebulaCoder/" prefix
: normalizedBody?.body ... ← correctly stripped
When the body parses successfully, it prefers the original body with the
Provider/ prefix. This prefixed model name reaches ai-gateway which only
knows bare model names, causing a 400.
Fix: always use normalizedBody.body (which strips the Provider/ prefix)
when available. Remove the now-unused bodyHasConfiguredProviderModelSelector.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>