mirror of
https://github.com/katanemo/plano.git
synced 2026-04-25 00:36:34 +02:00
drop synthesized default_model entry; wildcard expansion already handles bare names
This commit is contained in:
parent
c054523ecf
commit
f1a08196dc
2 changed files with 13 additions and 46 deletions
|
|
@ -27,10 +27,6 @@ class ProviderDefault:
|
|||
env_var: str
|
||||
base_url: str
|
||||
model_pattern: str
|
||||
# Concrete, small, cheap model to promote to `default: true` in the
|
||||
# synthesized config when this provider has an env key. Lets clients send
|
||||
# bare (unprefixed) model names that Plano otherwise rejects.
|
||||
default_model: str | None = None
|
||||
# Only set for providers whose prefix in the model pattern is NOT one of the
|
||||
# built-in SUPPORTED_PROVIDERS in cli/planoai/config_generator.py. For
|
||||
# built-ins, the validator infers the interface from the model prefix and
|
||||
|
|
@ -45,21 +41,18 @@ PROVIDER_DEFAULTS: list[ProviderDefault] = [
|
|||
env_var="OPENAI_API_KEY",
|
||||
base_url="https://api.openai.com/v1",
|
||||
model_pattern="openai/*",
|
||||
default_model="gpt-4o-mini",
|
||||
),
|
||||
ProviderDefault(
|
||||
name="anthropic",
|
||||
env_var="ANTHROPIC_API_KEY",
|
||||
base_url="https://api.anthropic.com/v1",
|
||||
model_pattern="anthropic/*",
|
||||
default_model="claude-haiku-4-5",
|
||||
),
|
||||
ProviderDefault(
|
||||
name="gemini",
|
||||
env_var="GEMINI_API_KEY",
|
||||
base_url="https://generativelanguage.googleapis.com/v1beta",
|
||||
model_pattern="gemini/*",
|
||||
default_model="gemini-2.5-flash",
|
||||
),
|
||||
ProviderDefault(
|
||||
name="groq",
|
||||
|
|
@ -79,14 +72,14 @@ PROVIDER_DEFAULTS: list[ProviderDefault] = [
|
|||
base_url="https://api.mistral.ai/v1",
|
||||
model_pattern="mistral/*",
|
||||
),
|
||||
# DigitalOcean Gradient is now a first-class provider (see #889) — model
|
||||
# prefix `digitalocean/` routes to the built-in cluster, no base_url needed.
|
||||
# DigitalOcean Gradient is a first-class provider post-#889 — the
|
||||
# `digitalocean/` model prefix routes to the built-in Envoy cluster, no
|
||||
# base_url needed at runtime.
|
||||
ProviderDefault(
|
||||
name="digitalocean",
|
||||
env_var="DO_API_KEY",
|
||||
base_url="https://inference.do-ai.run/v1",
|
||||
model_pattern="digitalocean/*",
|
||||
default_model="openai-gpt-5.4-mini",
|
||||
),
|
||||
]
|
||||
|
||||
|
|
@ -145,27 +138,12 @@ def synthesize_default_config(
|
|||
for p in detection.passthrough:
|
||||
model_providers.append(_entry(p, {"passthrough_auth": True}))
|
||||
|
||||
# Promote the first env-keyed provider that ships a `default_model` to a
|
||||
# concrete `default: true` entry. This lets clients send bare (unprefixed)
|
||||
# model names and still route somewhere sensible. Wildcards can't be marked
|
||||
# default (the validator rejects it), so we add a second concrete row.
|
||||
#
|
||||
# When no env keys are present, we leave `default` unset: the user is fully
|
||||
# in pass-through mode and must prefix model names so Plano knows which
|
||||
# upstream to route to.
|
||||
default_picked = next(
|
||||
(p for p in detection.with_keys if p.default_model is not None), None
|
||||
)
|
||||
if default_picked is not None:
|
||||
model_providers.append(
|
||||
{
|
||||
"name": f"{default_picked.name}/{default_picked.default_model}",
|
||||
"model": f"{default_picked.name}/{default_picked.default_model}",
|
||||
"base_url": default_picked.base_url,
|
||||
"access_key": f"${default_picked.env_var}",
|
||||
"default": True,
|
||||
}
|
||||
)
|
||||
# No explicit `default: true` entry is synthesized: the plano config
|
||||
# validator rejects wildcard models as defaults, and brightstaff already
|
||||
# registers bare model names as lookup keys during wildcard expansion
|
||||
# (crates/common/src/llm_providers.rs), so `{"model": "gpt-4o-mini"}`
|
||||
# without a prefix resolves via the openai wildcard without needing
|
||||
# `default: true`. See discussion on #890.
|
||||
|
||||
return {
|
||||
"version": "v0.4.0",
|
||||
|
|
|
|||
|
|
@ -44,24 +44,13 @@ def test_env_keys_promote_providers_to_env_keyed():
|
|||
assert by_name["anthropic"].get("passthrough_auth") is True
|
||||
|
||||
|
||||
def test_first_env_keyed_provider_becomes_default():
|
||||
def test_no_default_is_synthesized():
|
||||
# Bare model names resolve via brightstaff's wildcard expansion registering
|
||||
# bare keys, so the synthesizer intentionally never sets `default: true`.
|
||||
cfg = synthesize_default_config(
|
||||
env={"OPENAI_API_KEY": "sk-1", "ANTHROPIC_API_KEY": "a-1"}
|
||||
)
|
||||
defaults = [p for p in cfg["model_providers"] if p.get("default") is True]
|
||||
assert len(defaults) == 1
|
||||
# openai appears first in PROVIDER_DEFAULTS so it wins.
|
||||
assert defaults[0]["model"] == "openai/gpt-4o-mini"
|
||||
assert defaults[0]["access_key"] == "$OPENAI_API_KEY"
|
||||
|
||||
|
||||
def test_default_skips_providers_without_default_model():
|
||||
# Groq has no default_model wired up — the next env-keyed provider with one
|
||||
# should be picked instead.
|
||||
cfg = synthesize_default_config(env={"GROQ_API_KEY": "g", "ANTHROPIC_API_KEY": "a"})
|
||||
defaults = [p for p in cfg["model_providers"] if p.get("default") is True]
|
||||
assert len(defaults) == 1
|
||||
assert defaults[0]["model"].startswith("anthropic/")
|
||||
assert not any(p.get("default") is True for p in cfg["model_providers"])
|
||||
|
||||
|
||||
def test_listener_port_is_configurable():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue