镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

feat: let users name provider endpoints - #343

Merged
frostming merged 1 commit into
bubbuild:mainfrom
Gabyran:feat/custom-providers
Oct 9, 2026
Merged

frostming merged 1 commit into
bubbuild:mainfrom
Gabyran:feat/custom-providers

Conversation

@Gabyran

@Gabyran Gabyran commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Refs #342

What changed and why

api_key / api_base hold one value per any-llm provider, and the model prefix must be an any-llm provider, so every endpoint that speaks a supported API has to borrow that provider's slot. Real OpenAI and a proxy, two relays, or two accounts with one vendor can't be configured together, and setting api_base.openai for a relay also switches off Codex OAuth.

This adds a providers setting that names an endpoint and says which any-llm provider speaks for it. No new provider is added; any-llm still does the protocol work.

model: proxy:gpt-5.5
fallback_models:
  - openai:gpt-5.5
  - relay:claude-sonnet-5
providers:
  proxy:
    type: openai
    api_base: https://llm-proxy.example.com/v1
    api_key: sk-proxy-...
  relay:
    type: anthropic
    api_base: https://relay.example.com
    api_key: sk-relay-...

proxy: resolves to LLMProvider.OPENAI and relay: to LLMProvider.ANTHROPIC, each with its entry's base and key; openai: keeps its own api_key / api_base, or Codex OAuth. Fields left out fall back to api_key / api_base and BUB_<NAME>_API_*. An unknown type fails when settings load.

Impacted modules

  • src/bub/builtin/settings.py: CustomProvider, AgentSettings.providers, ModelCandidate.provider_name; model_candidates checks providers before AnyLLM.split_model_provider, model_client_kwargs reads the entry first
  • src/bub/builtin/model_runner.py: client kwargs are looked up by the prefix as written
  • Docs (en, zh-cn): a Custom providers section in reference/settings.mdx, one paragraph in operate/configure.mdx

Verification

  • uv run python -m pytest tests and uv run mypy on Python 3.12, 3.13 and 3.14 in a clean environment: 578 passed, 20 skipped; mypy clean
  • prek run on the change: pass
  • pnpm --dir website build: pass; #custom-providers / #自定义-provider anchors resolve
  • New tests: YAML providers beside builtin openai; env fallback; unknown type rejected; an openai-typed custom provider and Codex OAuth in one candidate list
  • End to end: a custom openai-typed provider pointed at a local OpenAI-compatible gateway answered, with a builtin fallback left in place

🤖 Generated with Claude Code

`providers` maps a name to an any-llm provider type plus its own
api_base/api_key, so `proxy:model` can sit beside `openai:model`.
Two endpoints that speak the same API (a proxy and the vendor, two
relays, two accounts), or a relay and Codex OAuth, no longer have to
share one provider slot.

Refs bubbuild#342

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@frostming frostming left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Elegant

@frostming
frostming merged commit 4e3dda0 into bubbuild:main Oct 9, 2026
5 checks passed
Gabyran added a commit to Gabyran/magpie that referenced this pull request Oct 9, 2026
…vider of its own (bubbuild/bub#343, merged)

Bub (bubbuild/bub) spells a model "<provider>:<model>", the provider one
of any-llm's or, from bubbuild/bub#343 on, a name under providers with its
own type, api_base and api_key. magpie adds providers.magpie (type openai,
the gateway's /v1, key magpie-bub, so Usage names Bub: its requests carry
the OpenAI SDK's User-Agent) and sets model to magpie:<provider>/<model>.
The model the user had is stashed and put back on disconnect; their own
providers, fallback_models and api_key are left alone, and a providers or
completion_args mapping magpie made goes again once empty. effort is
completion_args.reasoning_effort.

A model of Bub's own picked after magpie connected, in Bub or on the
Agents page, leaves magpie's provider in providers: Bub stays joined —
,model can name one of magpie's models again any time — and only
Disconnect takes the provider out (Joined and Unwire, as ed4476b gave
Hermes). Sync rewrites magpie's entry where it is, so a gateway key or
address that changed reaches a joined Bub too.

A Bub from before yetone#343 would take "magpie:" for an any-llm provider it
doesn't know and fail every turn, and yetone#343 is merged but not yet in a
release (0.5.0 was cut before it), so magpie asks the Python that runs
the bub on PATH whether its settings have providers and doesn't set one
of its models on one that says no (Check says so for a config set by
hand); one that can't be asked is the user's call. bub joins the testenv
stand-ins, as the probe runs it.
Gabyran added a commit to Gabyran/plugins that referenced this pull request Oct 11, 2026
…agpie-community#343 (review of magpie-community#81)

yetone's review of c2626cb asked for three things.

packages/bub/README.md, in aider's shape: the install line, the YAML magpie
writes, that `magpie bub default` puts it back, the restart advice, and the
Bub it needs. "README.md" is in package.json's files; `npm pack --dry-run`
lists it. The root README's Agents table gains Bub's row.

The notice and the README both name how to get a Bub with bubbuild/bub#343:
`uv tool install --reinstall git+https://github.com/bubbuild/bub`. No release
has magpie-community#343 yet (PyPI's latest is 0.5.0). A test fails when either one loses
the command; it went red with it taken out of the notice, and again out of
the README.

Run: bun test packages/bub (6 pass), bun scripts/check.mjs. In uv tool
directories of their own: PyPI's bub 0.5.0 has no `providers` and fails a
`magpie:` model with `'magpie' is not a supported provider`; after the
command above Bub is 0.5.1.dev16+g06aadff98, has `providers`, and answered
a turn through a fake OpenAI upstream, which got `Bearer magpie-bub`.
`uv tool install --reinstall` was the one tried: plain `uv tool install` over
an existing Bub was not.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Gabyran added a commit to Gabyran/plugins that referenced this pull request Oct 11, 2026
…e installing from git

Bub 0.5.1 is out (PyPI and GitHub release, 2026-10-11) and contains
bubbuild/bub#343, so the README, the notice and the root README's Agents
row say "Bub 0.5.1 or later" and how to update, in place of installing from
the repository.

The test that the notice and both halves of the README say it checks for
"0.5.1" and the update command, and the README's two halves for magpie-community#343. It went
red with the notice saying 0.5.0, and with the English half's command changed.

Run: bun test packages/bub (7 pass), bun scripts/check.mjs. Tried in
environments of their own: `uv tool install --reinstall bub` takes a pinned
0.5.0 to 0.5.1, and `pip install -U bub` takes a venv's 0.5.0 to 0.5.1, each
with `providers` in Bub's settings; each of the two answered a turn on a
`magpie:` model through a fake OpenAI upstream, which got `Bearer magpie-bub`.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Gabyran added a commit to Gabyran/plugins that referenced this pull request Oct 11, 2026
…ew of magpie-community#81)

yetone's re-review of edc9c39 asked for the repo's order: every other
package README is English (22 of them), as are the description fields, and
the npm page and the plugin row are read by people who don't read Chinese as
well. So the English README comes first with "(中文说明在下面。)" at the top and
the Chinese one follows under "## 中文"; description says the English first.

The two README tests are turned around: split on "## 中文", each half names
0.5.1, the update command and bubbuild/bub#343 (the notice, 0.5.1 and the
command), and the English half is free of Chinese but for the pointer, the
Chinese half has it. Each went red with its guarantee taken out (the halves
swapped, the update command changed in the Chinese half).

Run: bun test packages/bub (7 pass), bun scripts/check.mjs; `npm pack
--dry-run` lists README.md, bub.agent.js and package.json.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
yetone pushed a commit to magpie-community/plugins that referenced this pull request Oct 28, 2026
Adds packages/bub: Bub (bub.build) as a magpie agent plugin. It writes
~/.bub/config.yml with the model as magpie:<provider>/<model> and a
providers.magpie entry (type openai, magpie's /v1, Bub's own key), and
puts the file back when one of Bub's own models is picked or it is turned
off. Needs Bub 0.5.1 or later (bubbuild/bub#343). Plus its row in the
README's Agents table, which is now in alphabetical order.

Reviewed at 4b879fb (2026-10-11), with a real Bub 0.5.1 run against a
sandbox magpie. Since then only merges of main; the PR's own diff from the
merge base is the five files above, packages/bub unchanged since 4b879fb.
It waited only for a first npm publish, which the repo no longer requires
(README: a new plugin merges once its review is done; served from dist).

Run on mote at the merged tree (origin/main 202ec68 + head 13058fe),
Bun 1.4.2: bun test packages/bub 7 pass; bun scripts/check.mjs all ok;
whole bun test with a temp HOME and TMPDIR 2949 pass, 8 skip, 0 fail.

Co-authored-by: Gabyran <Gabyran@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants