Skip to content

feat(gateway): one base URL per card - #278

Merged
T-Crypt merged 2 commits into
nextfrom
T-Crypt/gateway-card-urls
Oct 31, 2026
Merged

T-Crypt merged 2 commits into
nextfrom
T-Crypt/gateway-card-urls

Conversation

@T-Crypt

@T-Crypt T-Crypt commented Oct 31, 2026

Copy link
Copy Markdown
Owner

First slice of v0.5: per-card gateway endpoints.

What changes for users

On a node with several cards, a client can now pick the card. Each card has a base URL on the gateway, /cards/CARD/v1, where CARD is the card's name (gpu1) or its PCI address. A request through it only reaches engines whose [[engine]] entry runs on that card, and GET /cards/CARD/v1/models lists only their models. One model can be served on several cards, one entry per card on its own port, so http://127.0.0.1:9799/cards/gpu1/v1 and .../cards/gpu0/v1 reach different copies under the same model name.

Nothing changes without the prefix. A plain /v1 request goes to the first entry that serves the model, as before. berth config check still refuses two entries that serve one model on the same card, or where either names no card.

How

  • onCard wraps the chat, completions, embeddings, models and berth/wait handlers. It resolves the card through berthd's status with the same match node.View uses, puts the card's name in the path value, and strips the prefix so the engine sees /v1/....
  • resolve and catalog take the card and keep only engines whose entry's gpu picks it (node.CardsOf, exported from cardsOf). An engine berthd finds with no entry in berth.toml belongs to no card, so only the plain URL reaches it.
  • Config: the per-model check keeps every serving entry and conflicts only when two share a card (sharesCard).

Proof

  • TestCardBaseURLPicksTheEngineOnThatCard runs two fake engines on a two-card berthd. It checks routing by card name and by PCI address, the unprefixed route, a model asked on the wrong card (404 naming the card), an unknown card (404 listing the cards) and the per-card model list. It fails before the feature commit.
  • TestOneModelOnTwoCards accepts qwen on gpu0 and gpu1, and refuses gpu1 with gpu1, and no card with gpu1. It fails before the feature commit.
  • Mutation: removing the card filter from resolve sends gpu1 requests to gpu0 and the test fails.
  • Build, gofmt, vet, go test ./..., the Windows build and vet, and golangci-lint (0 issues) all pass.

Next slices

Placement among the copies for a plain /v1 request, then cordoning a card, then a card picker on the harbor board.

One model served by an engine on gpu0 and another on gpu1. A request to
/cards/gpu1/v1 must reach gpu1's engine, a card named by its PCI address
must work, an unknown card is a 404 listing the cards, and the card's
model list names only its engines' models. berth config check must accept
the two entries. Both tests fail until the routes and the config rule land.
/cards/CARD/v1 takes chat, completions, embeddings, models and
berth/wait. CARD is the card's name or PCI address. The gateway resolves
the model among the engines whose entry runs on that card and strips the
prefix before it proxies. berth config check now lets one model be served
by one engine per card, and still refuses two on one card or where one
names no card. A request without the prefix is routed as before.

First slice of v0.5, per-card gateway endpoints.
@T-Crypt
T-Crypt merged commit 6135a6a into next Oct 31, 2026
4 checks passed
@T-Crypt
T-Crypt deleted the T-Crypt/gateway-card-urls branch November 2, 2026 15:02
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.

1 participant