Skip to content

feat: add Maxlayer provider - #5169

Open
kerjakuyco wants to merge 12 commits into
anomalyco:devfrom
kerjakuyco:provider/maxlayer
Open

feat: add Maxlayer provider#5169
kerjakuyco wants to merge 12 commits into
anomalyco:devfrom
kerjakuyco:provider/maxlayer

Conversation

@kerjakuyco

@kerjakuyco kerjakuyco commented Aug 21, 2026

Copy link
Copy Markdown

Adds Maxlayer (https://maxlayer.cloud) — a multi-model inference gateway serving 399 models through an OpenAI-compatible endpoint at https://inference.maxlayer.cloud/v1. (Disclosure: I work on Maxlayer.)

What's included

  • provider.toml@ai-sdk/openai-compatible, MAXLAYER_API_KEY
  • logo.svg (currentColor)
  • 163 rate-carded text models as base_model references, across 20 publishers (OpenAI, Qwen, Google, Anthropic, Z.ai, DeepSeek, MiniMax, Moonshot, xAI, NVIDIA, Mistral, Cohere, Meta, ByteDance Seed, StepFun, Tencent, Xiaomi and others)

Data sourcing

Pricing is mirrored from the public catalogue endpoint GET /v1/models (no key required). pricing.input_per_million_tokens and its siblings are the rate a caller is billed, already in USD per million tokens, mapped to input / output / cache_read / cache_write. The response also carries base_*_per_million_tokens fields — a display-only reference rate — which are deliberately not what this PR publishes; Maxlayer does mark up token rates, so costs sit above those reference figures rather than matching them. The card is flat: there is no band or threshold field anywhere in the payload, so no [[cost.tiers]] are authored even for IDs that are tiered on other hosts.

Limits come from the same endpoint — context_windowlimit.context on all 163 files, max_output_tokenslimit.output on 152. Eleven routes publish no max output; those follow the same-surface peer entries in this repository rather than the lab default, which was short enough to misreport them badly (meta/muse-spark-1.1 resolves to 1_048_576, not 32_000).

Capabilities and reasoning_options are not published by this endpoint — the model list carries no supported_parameters, no modality list, and an empty capabilities array on every row. Rather than guess, both are set to match the same-surface peer entries in this repository for the same model ID: structured_output on 76 files, modalities on 38, and name / temperature / tool_call / attachment on a handful each. 162 of 163 files match the peer's reasoning shape exactly; the exception is openai/o1-pro, which carries graded effort to match the lab entry and every other host serving it. Where a file carries a toggle it also carries the leading wire-path comment naming the accepted request fields.

Every file uses base_model and is override-only — no file restates a value the lab entry already carries, nested limit keys included.

The full live catalogue is 399 models. This PR covers the 163 rate-carded text models with a canonical lab entry; the remainder are 140 text models with no lab entry yet, 66 image and video models billed at actual request cost rather than from a rate card, and 30 embedding models.

bun validate passes locally.

kerjakuyco and others added 6 commits August 21, 2026 09:07
Maxlayer is an OpenRouter-fronted gateway with an OpenAI-compatible
endpoint at https://inference.maxlayer.cloud/v1. It relays to OpenRouter
and keeps OpenRouter's `publisher/model` IDs verbatim, so a Maxlayer ID
resolves onto the same canonical metadata the OpenRouter sync uses and
every model file stays override-only over `base_model`.

The sync module is authoritative for price and nothing else. Maxlayer's
`GET /v1/models` publishes one `category` string and a `capabilities`
array that is empty on every synced row -- no `supported_parameters`, no
modality list, no reasoning metadata -- so a model with no canonical
match is skipped and reported rather than authored from guesses. That
covers 163 of the 303 rate-carded text models; the remainder need a
`models/<lab>/<model>.toml` upstream first.

Two things the response cannot supply are read from the sibling
OpenRouter provider file for the same ID: `reasoning_options`, which is
required whenever the base declares `reasoning = true`, and a
`limit.output` fallback for the 60-odd rows publishing a null
`max_output_tokens`. Both are sound here because Maxlayer forwards the
request body to OpenRouter unchanged, so the controls a caller sends are
OpenRouter's, model for model.

Prices are written from `pricing.input_per_million_tokens`, which is the
sell price -- upstream's rate plus the credit fee and the platform
markup, derived on every read. The sibling `base_*_per_million_tokens`
fields carry upstream's own rate for display only and are deliberately
not read; quoting those would undercharge every model on the list.

`upstream_cost` models (image, video, multimodal embeddings) are out of
scope: they bill what the request actually cost and publish no rate card
to express. Plain embeddings are out of scope too, as they are for the
OpenRouter provider.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A `toggle` reasoning option needs a leading comment naming the exact
request field, since sync re-serializes these files and keeps only a
leading block. 55 of the 163 files carry a toggle and none carried the
header.

The fields are OpenRouter's because that is the API a Maxlayer request
reaches -- the body is forwarded unchanged, so `reasoning.enabled`,
`reasoning.effort`, and `reasoning.max_tokens` are what a caller sends
here too. The header says so rather than leaving a reader to wonder why
a Maxlayer file cites OpenRouter's docs.

Emitted from `translateModel` via the runner's `header` hook, so it
applies only to files that actually have a toggle and a hand-written
header on an existing file still wins. Change detection compares parsed
model data and ignores comments, so the files were regenerated rather
than updated in place; the diff is 330 added comment lines across 55
files and nothing else.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The five keys say it; the routes, the key prefix, and the missing SDK
were notes for review rather than facts a catalog consumer reads.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The toggle header carried two lines of prose about where a Maxlayer
request goes after it leaves, and a link to the upstream's docs. Neither
is something a catalog consumer needs: what a caller sends is the wire
path, and that is all the header has to name.

Leaves the three field lines the toggle policy asks for, on the same 55
files. No model data changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`openRouterReasoningOptions` pushed the toggle from inside the branch
that handles graded effort, so a model publishing `reasoning.mandatory =
false` with no `supported_efforts` and no `supports_max_tokens` produced
no options at all. The runner then backfilled `reasoning_options = []`,
which does not mean "unknown" -- it asserts the caller has no control.
These models do have one: reasoning is on by default and
`reasoning.enabled` turns it off.

Fixes 69 files. Each one is a model the upstream catalog reports as
non-mandatory, and peers serving the same base model already publish a
toggle -- `moonshotai/kimi-k2.6` had 41 of them.

Confined to reasoning options on purpose. minimax-m2.5 also had upstream
price drift; that is left for the daily sync rather than folded in here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reasoning options were read as `existing?.reasoning_options ?? sibling`,
and `[]` is not nullish, so once the runner had backfilled an empty array
the file could never learn anything better. The sibling files gained real
toggles in the previous commit and all 13 affected models stayed empty
until this changed. An empty array is the runner's placeholder for "no
one supplied controls", never something an author chose, so it now loses
to a sibling that has them.

Every remaining empty is now provably right: 11 models the upstream
catalog marks mandatory, where reasoning is always on and there is
nothing to switch, and 2 that report no reasoning at all.

Prices in the same 21 files moved because the live catalogue refreshed
between syncs. All 163 match the published sell price exactly and the
realised markup is uniform.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] packages/core/src/sync/providers/openrouter.ts:5410 - Check: Relay reasoning_options must match the host’s real controls and must not invent a thinner set than lab/peers when API metadata is incomplete. Why: The new else if (!reasoning.mandatory) branch returns [{ type: "toggle" }] whenever supported_efforts is absent. Because openRouterReasoningOptions(...) is preferred whenever it returns any array, that sparse result replaces richer authored options instead of only fixing empty []. The diff drops real controls on many models (e.g. o1/o3/o3-mini/o3-pro/o4-mini lose effort low/medium/high; Claude Opus 4.5 / Haiku 4.5 / Sonnet 4.5 and several Qwen rows lose effort and/or budget_tokens). First-party OpenAI o-series files still author effort L/M/H (not toggle-only); o1-pro first-party is effort, not toggle. Catalog consumers will be told the wrong wire surface. Action: Only emit toggle-from-incomplete-metadata when there is nothing better to keep (e.g. existing is missing/[]). If the API omits efforts/budget but the file already has them, preserve or merge those options. Restore effort/budget on the affected OpenRouter TOMLs to match first-party + prior same-surface peers, then re-sync Maxlayer so sibling copies stay aligned.
  • [medium] [violation] providers/openrouter/models/openai/o1.toml:3 - Check: Every toggle needs a leading top-of-file wire-path comment (AGENTS.md → Reasoning options). Why: Patch 5 introduces type = "toggle" on dozens of OpenRouter files (o-series, Kimi, GLM, free routes, etc.) with no leading # Toggle: … comment. Maxlayer correctly emits headers for the same control surface; OpenRouter does not. Action: Add a leading wire comment on every OpenRouter file that gains a toggle (e.g. # Toggle: reasoning.enabled = true|false), or teach the OpenRouter sync header hook the same way Maxlayer/LLM Gateway do.
  • [low] [possible mistake] .pr-review/pull-request.json:4 - Check: Data-changing PRs should cite first-party pricing/docs/API and map each citation to claims. Why: The body explains Maxlayer’s rate-card behavior and OpenRouter forwarding, but does not list direct Maxlayer pricing/docs URLs or state what each source supports for the published sell prices / control surface. Action: Add first-party Maxlayer (and, for the OpenRouter reasoning fix, OpenRouter reasoning) doc/API citations mapped to cost and reasoning_options claims.

kerjakuyco and others added 2 commits August 21, 2026 11:26
This reverts commit 0c009b7.

The bug is real, but it belongs in its own pull request rather than
inside one that adds a provider. Rewriting 69 files in a provider this
PR does not own buries the thing under review.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Leaves the model files as authored TOMLs, which is the shape a provider
addition takes here, and confines the change to `providers/maxlayer/`.

The module and its registration are worth having and are kept in this
branch's history at 335ce01 if we want them in a follow-up. They are
removed here because a sync module carries a reproducibility contract --
running it must reproduce the committed files -- and honouring that for
13 reasoning models needs a fix in a provider this PR should not touch.
Authored files make the same 13 an ordinary claim about the host's API,
reviewable on its own terms.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/maxlayer/models/qwen/qwen-plus.toml:2 - Check: Relay reasoning / reasoning_options must match this host’s surface and same-surface peers; [] means no caller control, not “non-reasoning.” Why: Canonical models/alibaba/qwen-plus.toml has reasoning = true. Maxlayer sets reasoning_options = [] without overriding reasoning, so the resolved model is a reasoner with no controls. Same-ID OpenRouter/Kilo peers set reasoning = false for this route; Alibaba first-party uses toggle + budget. Maxlayer matches neither. Action: Set reasoning = false (and drop reasoning_options) to match the OpenRouter-shaped peer, or author the real OpenRouter/lab controls if this Maxlayer ID actually reasons.
  • [high] [possible mistake] providers/maxlayer/models/openai/o1-pro.toml:7 - Check: Relay reasoning baseline = lab + same-surface peers; do not invent a toggle when the native control is effort. Why: Final Maxlayer file is toggle only (with a reasoning.enabled header). OpenAI lab and other relays use graded effort (low/medium/high on lab; Kilo uses effort). OpenRouter currently has []. A binary reasoning.enabled toggle is not the o1-pro control surface and contradicts the lab baseline. Action: Replace with effort values matching lab/peers (typically ["low", "medium", "high"]), or justify with Maxlayer/OpenRouter evidence if this ID truly has only on/off and no effort.
  • [low] [possible mistake] .pr-review/pull-request.json (PR body) - Check: Data-changing provider PRs should cite first-party pricing/docs/API and map each citation to claims. Why: Body describes the gateway and sell-price fields but does not link Maxlayer pricing/docs/API evidence for the ~163 cost rows or the OpenRouter-forwarding / reasoning.* wire claims. Action: Add direct Maxlayer (and, if relied on, OpenRouter reasoning) URLs and state what each supports (sell rates, ID shape, request forwarding, reasoning fields).

`qwen/qwen-plus` and `minimax/minimax-m2-her` inherited `reasoning =
true` from their lab entries and carried `reasoning_options = []`, so
each resolved to a reasoner with no controls. Neither route reasons:
the host catalogue publishes no reasoning parameters for them, and the
OpenRouter, Kilo and nano-gpt entries for the same IDs all set
`reasoning = false`. Now they do too, with no options.

`openai/o1-pro` had a toggle. Its control is graded effort -- OpenAI
first-party, poe, cloudflare-ai-gateway and edenai all author
`["low", "medium", "high"]`, and no entry anywhere uses a toggle for it.
Replaced, and the wire header went with it since there is no longer a
toggle to document.

Checked the rest of the class rather than only these: of 31 toggle-only
files, 30 have `toggle` as a leading shape among peers serving the same
base model, and o1-pro was the only outlier. Of the 13 files with empty
options, 11 have `[]` as the dominant peer shape and are models the host
catalogue marks reasoning-mandatory, where there is genuinely nothing to
switch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [medium] [possible mistake] providers/maxlayer/models/openai/o1-pro.toml:1 - Check: Relay host capability overrides vs claimed OpenRouter-identical surface. Why: The PR states Maxlayer forwards the OpenRouter request body unchanged and keeps the same IDs, but several Maxlayer files only override cost/reasoning and still inherit lab capabilities that OpenRouter explicitly narrows. Concrete gaps vs providers/openrouter/models/... for the same IDs: openai/o1-pro lacks tool_call = false (and PDF modality); openai/gpt-4 lacks attachment = false / structured_output = true; minimax/minimax-m2-her lacks tool_call = false / structured_output = false; deepseek/deepseek-chat lacks attachment = false; moonshotai/kimi-k2.5 lacks temperature = true. Catalog consumers will overstate tools/attachments/modalities on this host. Action: For every Maxlayer ID that has an OpenRouter sibling, copy real capability deltas (tool_call, attachment, structured_output, temperature, [modalities], etc.) from that sibling (or verify Maxlayer’s own /v1/models/docs and document intentional differences).
  • [low] [possible mistake] providers/maxlayer/models/anthropic/claude-opus-4.6.toml:11 - Check: Context-tier pricing ([[cost.tiers]]) when the rate card is multi-band. Why: Same-ID OpenRouter entries (e.g. claude-opus-4.6, claude-sonnet-4.5, openai/gpt-5.4, x-ai/grok-4.6, qwen/qwen3.6-plus) publish context tiers, but Maxlayer only authors a single flat [cost] band. If Maxlayer’s sell price is also tiered, long-context quotes will be wrong; if the published Maxlayer card is intentionally flat, that needs a short PR note. Action: Confirm against Maxlayer pricing/GET /v1/models whether any model has context (or other) bands; add [[cost.tiers]] where they exist, or cite that Maxlayer bills a single band for those IDs.
  • [low] [possible mistake] .pr-review/pull-request.json:4 - Check: Data-changing PRs should cite direct provider pricing/docs/API mapped to claims. Why: ~160 models introduce sell-side USD costs and host reasoning surfaces with no PR-body links stating what each source supports (Maxlayer rate card, docs for reasoning.enabled / effort / budget, and any non-OR capability claims). Reviewers cannot validate the markup fractions or wire path from the catalog alone. Action: Add first-party Maxlayer citations (pricing page and/or GET https://inference.maxlayer.cloud/v1/models, plus inference docs) and note which claims each URL supports.

The model files overrode cost, limits and reasoning and nothing else, so
every capability the host narrows was silently inherited from the lab
entry. A consumer reading the catalog would have been told o1-pro takes
tools, gpt-4 takes attachments, and MiniMax-M2-Her does structured
output -- none of which is true on this host.

Copies the real deltas for 112 files: structured_output on 76,
modalities on 38, and name, temperature, tool_call and attachment on a
handful each. Each value was taken only where it genuinely differs from
the lab entry, so the files stay override-only; nothing restates a value
the base already carries.

`name` is in that set because six IDs are variant routes -- the
`-fast` and `-pro` lanes -- whose lab entry is the unsuffixed model.
Descriptions were left alone: they are editorial rather than a statement
about what this host can do.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/maxlayer/models/minimax/minimax-m3.toml:6 - Check: Relay reasoning_options must match this host’s wire surface (lab + same-surface peers), not a temporary sibling edit. Why: Maxlayer is documented as an OpenRouter-fronted passthrough, yet these files author toggle while the established OpenRouter peers for the same IDs use reasoning_options = [] (always-on / no caller control): minimax-m3, moonshotai/kimi-k2.5, kimi-k2.6, nvidia/nemotron-3-nano-30b-a3b, and z-ai/glm-4.6, glm-4.6v, glm-4.7, glm-4.7-flash, glm-5, glm-5.1, glm-5-turbo, glm-5v-turbo. Those toggles were introduced by copying a later-reverted OpenRouter change; leaving them claims a reasoning.enabled control this surface does not catalog. Action: For each ID, set Maxlayer to the OpenRouter same-surface shape ([] unless Maxlayer docs/tests prove a real on/off field), drop the toggle wire headers where toggle is removed, and do not keep lab-only toggles without host evidence.
  • [medium] [possible mistake] providers/maxlayer/models/anthropic/claude-opus-4.6.toml:14 - Check: Context-based pricing must be authored as [[cost.tiers]] when this host bills higher bands. Why: OpenRouter peers for claude-opus-4.6, claude-opus-4.7, claude-sonnet-4.5, and claude-sonnet-4.6 publish 200k context tiers; Maxlayer only lists flat [cost] (roughly OR base × markup). If Maxlayer also tiers long context, the catalog understates sell price above the threshold. Action: Verify Maxlayer’s rate card for these models; if higher context bands exist, add matching [[cost.tiers]] (marked-up), otherwise note in the PR that Maxlayer is flat-rate only.
  • [low] [possible mistake] .pr-review/pull-request.json:4 - Check: Data-changing PRs should cite first-party pricing/docs/API and map each citation to claims. Why: The body describes the gateway and ID scheme but does not cite Maxlayer pricing docs, GET /v1/models field meanings, or evidence for the capability deltas in patch 10 (structured_output, modalities, tool_call, etc.). Action: Add direct Maxlayer (and any needed peer) URLs stating what each supports—sell-rate fields, limits, and capability overrides.

These twelve authored `reasoning_options = [{ type = "toggle" }]` while
the established entries for the same twelve IDs carry `[]`. The toggles
came from a sibling change that was later reverted out of this branch,
so they were left claiming a `reasoning.enabled` control that nothing in
the catalog documents. They now carry `[]`, matching the same-surface
peer, and the wire headers went with them since there is no longer a
toggle to name.

The upstream catalogue does report these as non-mandatory, which is what
prompted the toggles in the first place. That is a real finding but it is
a finding about the peer entry, not this one: the peer says `[]` for all
twelve, and a relay should not be the only place in the catalog claiming
a control. Correcting it belongs in the change that fixes the peer, where
both providers move together.

Reasoning options are now identical to the peer for 162 of 163 files. The
exception is `openai/o1-pro`, which review asked to carry graded effort
to match the lab entry and every other relay.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [medium] [possible mistake] providers/maxlayer/models/meta/muse-spark-1.1.toml:13 - Check: Provider limits must reflect this host (or same-surface peer when the host API is silent). Why: Maxlayer only overrides limit.context = 1_048_576, so limit.output stays the lab default (32_000). The same-ID OpenRouter peer (the surface this PR says Maxlayer forwards to) overrides limit.output = 1_048_576. Catalog consumers will understate max output on this route. Action: Verify Maxlayer’s served max output for meta/muse-spark-1.1; if it matches OpenRouter, add limit.output = 1_048_576 (and do the same check for muse-spark-1.2, which also lacks OpenRouter’s output = 1_048_576 override).
  • [medium] [possible mistake] providers/maxlayer/models/moonshotai/kimi-k3.toml:1 - Check: Same-surface peer limit overrides for a faithful OpenRouter relay. Why: This file has no [limit] override, so resolved output stays the lab 131_072. OpenRouter’s moonshotai/kimi-k3 sets limit.output = 1_048_576. If Maxlayer truly shares that route, the catalog is wrong. Action: Confirm Maxlayer’s max output for moonshotai/kimi-k3 and add a matching limit.output override when the peer value is correct.
  • [low] [possible mistake] .pr-review/pull-request.json (PR body) - Check: Data-changing PRs should cite first-party pricing/docs/API with what each source supports. Why: The body explains architecture and sell-price semantics but does not map a Maxlayer pricing or models endpoint citation to the published USD/MTok figures or capability deltas. Action: Add direct Maxlayer docs/API links and note which claims each supports (sell rates, limits, modalities, reasoning wire fields).

`limit.output` came from the host's `max_output_tokens` wherever it was
published, and fell back to the lab entry where it was null. For eleven
routes the host publishes nothing, and the lab default was well short of
what the route actually serves: muse-spark-1.1 was capped at 32_000
against a 1_048_576 context, grok-4.3 at 30_000 against 1_000_000.

Those eleven now take the same-surface peer's value, which is the best
evidence available when the host is silent. Seven changed. One moved
down rather than up -- nemotron-3-ultra-550b-a55b serves 16_384, not the
lab's 128_000 -- which is the same rule applied honestly rather than a
search for larger numbers.

Not guesswork for the rest: `limit.context` matches the host's published
`context_window` on all 163 files, and `limit.output` matches the host's
own `max_output_tokens` on the 152 where it publishes one. No file
restates a limit the lab entry already carries, and none claims an
output larger than its context.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Checking whether any structured_output overrides duplicate the lab value (redundant override blocker).

@kerjakuyco

Copy link
Copy Markdown
Author

Checking whether any structured_output overrides duplicate the lab value (redundant override blocker).

0 redundant overrides across all 163 files.

@kerjakuyco
kerjakuyco marked this pull request as draft August 21, 2026 07:44
@kerjakuyco
kerjakuyco marked this pull request as ready for review August 21, 2026 07:44
@github-actions

Copy link
Copy Markdown
Contributor

No actionable findings.

@github-actions github-actions Bot added the reviewer: ready Automated review found no actionable items label Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

reviewer: ready Automated review found no actionable items

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant