aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/superpowers/plans/2026-08-09-external-providers.md40
1 files changed, 35 insertions, 5 deletions
diff --git a/docs/superpowers/plans/2026-08-09-external-providers.md b/docs/superpowers/plans/2026-08-09-external-providers.md
index a17c1d9..0c8fc19 100644
--- a/docs/superpowers/plans/2026-08-09-external-providers.md
+++ b/docs/superpowers/plans/2026-08-09-external-providers.md
@@ -137,6 +137,26 @@ def test_provider_parsing():
# Unset numbers stay None so "unknown" is distinguishable from zero.
assert parsed["local"].ctx_size is None
assert parsed["local"].price_in is None
+
+ # A [providers.local] that omits base_url inherits the bare one rather
+ # than shadowing the local provider out of existence.
+ partial = providers.parse(
+ {
+ "base_url": "http://localhost:8181",
+ "providers": {"local": {"api_key": "env:SOME_VAR"}},
+ }
+ )
+ assert set(partial) == {"local"}
+ assert partial["local"].base_url == "http://localhost:8181"
+ # The explicit entry's own fields survive the merge.
+ assert partial["local"].api_key == "env:SOME_VAR"
+
+ # A filter given as a bare string is one needle, not four.
+ stringy = providers.parse(
+ {"providers": {"p": {"base_url": "http://x.example.org",
+ "filter": "qwen"}}}
+ )
+ assert stringy["p"].filter == ["qwen"]
print("ok provider config parsing")
```
@@ -210,11 +230,15 @@ def parse(values: dict) -> dict[str, Provider]:
"""
table = dict(values.get("providers") or {})
- # An old config has only a bare base_url. Synthesize the local provider
- # from it so nothing needs migrating, but never override an explicit one.
+ # An old config has only a bare base_url. Fill it in as the local
+ # provider's URL so nothing needs migrating, but never override an
+ # explicit one. The test is the URL rather than the key: a
+ # [providers.local] that only sets an api_key is adding detail to the
+ # provider the user already has, not replacing it, and treating it as a
+ # replacement would silently delete local entirely.
bare = values.get("base_url")
- if bare and LOCAL not in table:
- table[LOCAL] = {"base_url": bare}
+ if bare and not (table.get(LOCAL) or {}).get("base_url"):
+ table[LOCAL] = {**(table.get(LOCAL) or {}), "base_url": bare}
out: dict[str, Provider] = {}
for name, entry in table.items():
@@ -224,12 +248,18 @@ def parse(values: dict) -> dict[str, Provider]:
# ponytail: a provider with no URL is misconfigured, not a
# partial one. Skipping beats inventing a default endpoint.
continue
+ # filter = "qwen" is an easy TOML slip for filter = ["qwen"], and
+ # iterating the string would turn it into four single-character
+ # needles that match nearly every model id.
+ needles = entry.get("filter") or []
+ if isinstance(needles, str):
+ needles = [needles]
vision = entry.get("vision")
out[str(name)] = Provider(
name=str(name),
base_url=base_url,
api_key=str(entry.get("api_key") or ""),
- filter=[str(f) for f in (entry.get("filter") or [])],
+ filter=[str(f) for f in needles],
ctx_size=_number(entry.get("ctx_size"), int),
vision=None if vision is None else bool(vision),
price_in=_number(entry.get("price_in"), float),