Skip to content

feat: add PPIO provider - #7567

Open
hu-miao wants to merge 1 commit into
anomalyco:devfrom
hu-miao:add-ppio-provider
Open

hu-miao wants to merge 1 commit into
anomalyco:devfrom
hu-miao:add-ppio-provider

Conversation

@hu-miao

@hu-miao hu-miao commented Sep 20, 2026

Copy link
Copy Markdown

Adds the PPIO provider, serving 46 open-weight models through its OpenAI-compatible endpoint.

Provider

  • api = "https://api.ppio.com/openai/v1", npm = "@ai-sdk/openai-compatible", env = ["PPIO_API_KEY"]
  • Model ids mirror PPIO's own /openai/v1/models ids, so catalog keys match what the API accepts.

Models

46 open-weight models across DeepSeek, MiniMax, Moonshot AI, Qwen, Xiaomi, and Z.ai. Every entry uses base_model and overrides only what differs from the lab entry: cost, plus limit, modalities, structured_output, reasoning_options, and interleaved where PPIO's API reports something different.

Pricing

PPIO lists prices in CNY per million tokens. Converted at CNY→USD 6.718405 (2026-09-20, https://open.er-api.com/v6/latest/USD); the rate, date, and source are recorded in each model file's header.

Nine models use context-tiered pricing, expressed with [[cost.tiers]] and the lowest band as the base [cost].

Two models needed a note on where the rate applies:

  • glm-4.7 — PPIO splits the 1–32000 context band by output length (≤200 output tokens at CNY 2/8, above at CNY 3/14). cost.tiers is context-only, so the general-case rate is used for that band. cache_write is published only for the 32000+ band.
  • glm-4.6vcache_read is published only for the 32768+ band.

Reasoning

reasoning_options follows PPIO's thinking-mode documentation:

Models Options
deepseek-v4-pro-0813, deepseek-v4-flash-0731 toggle + effort (low/high/max)
glm-5.3, glm-5.3-flash, kimi-k3 effort (low/high/max) — thinking is always on
minimax-m3 toggle (thinking.type = adaptive/disabled)
remaining models [] — no documented caller control on this host

For the models with []: PPIO's chat-completions reference exposes no general reasoning_effort or thinking parameter. Its enable_thinking is documented only for deepseek/deepseek-v3.2-exp and separate_reasoning only for deepseek/deepseek-r1-turbo, neither of which is in this PR.

interleaved = { field = "reasoning_content" } is set for kimi-k3, minimax-m3, minimax-m2.7, and minimax-m2.7-highspeed, which document that side channel (the MiniMax models via reasoning_split = true).

Validation

  • bun validate passes
  • bun run test in packages/sdk passes (23 tests)

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [possible mistake] providers/ppio/models/deepseek/deepseek-v4-pro.toml:5 - Check: Relay reasoning_options must match this host’s real controls (and must not use [] from uncertainty when lab/peers expose controls). Why: deepseek-v4-pro, deepseek-v4-flash, deepseek-v4.1-flash, and deepseek-v4-flash-vision-exp set reasoning_options = [], while the same PPIO catalog gives toggle + effort (low/high/max) to dated siblings deepseek-v4-pro-0813 / deepseek-v4-flash-0731, and first-party DeepSeek plus established relays expose thinking controls for these undated IDs. Empty means “no caller control,” not “unlisted in one doc page.” Action: Confirm on PPIO’s chat API whether these four IDs accept the same thinking.type / reasoning_effort surface as the dated snapshots (or first-party). If they do, author matching reasoning_options (and wire comments); only keep [] with host-specific evidence that these IDs truly reject caller control.
  • [medium] [violation] providers/ppio/models/zhipuai/glm-4.5v.toml:15 - Check: After base_model, provider files must be override-only (no restated identical fields). Why: [modalities] input = ["text", "image", "video"] matches models/zhipuai/glm-4.5v.toml exactly, so the override is redundant and violates the override-only rule. Action: Remove the identical [modalities] block; keep only real deltas (e.g. limit.context = 65_536).
  • [medium] [possible mistake] providers/ppio/models/deepseek/deepseek-v4-pro-0813.toml:6 - Check: Provider-authored interleaved when this host returns a reasoning side channel. Why: deepseek-v4-pro-0813 and deepseek-v4-flash-0731 enable thinking controls, but neither sets [interleaved]. First-party DeepSeek and most OpenAI-compatible peers for these models set field = "reasoning_content". Omitting it understates the response shape if PPIO splits reasoning the same way (as already documented for MiniMax via reasoning_split). Action: Verify PPIO chat completions for these IDs; if reasoning is returned on reasoning_content (or reasoning_details), add the matching [interleaved] block.

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/ppio/models/alibaba/qwen3.5-122b-a10b.toml:4 - Check: Every toggle must have a leading top-of-file wire comment. Why: Many PPIO models set reasoning_options with type = "toggle" but only have CNY/pricing headers—no Toggle: … path. AGENTS.md and the reasoning-options audit require the exact request field (e.g. thinking.type = enabled|disabled) above the first key so clients know the wire shape. Action: Add a leading # Toggle: thinking.type = enabled|disabled (or the measured values, e.g. adaptive|disabled for M3) on every toggle model that lacks it, including the Qwen 3.5/3.6/3.8-27b, DeepSeek V4 non-dated (deepseek-v4-flash, deepseek-v4-pro, deepseek-v4.1-flash, deepseek-v4-flash-vision-exp), Kimi (kimi-k2.6), Xiaomi MiMo, and Zhipu GLM toggle entries. Keep the existing comments on deepseek-v4-*-0813/-0731, minimax-m3, and kimi-k3.
  • [medium] [possible mistake] providers/ppio/models/moonshotai/kimi-k3.toml:17 - Check: Provider limit overrides must reflect this host’s real caps, not lab context mistaken for output. Why: Lab moonshotai/kimi-k3 has limit.output = 131_072 and limit.context = 1_048_576. PPIO only overrides output = 1_048_576, which is the lab context size and is an order of magnitude above the lab output cap. Action: Confirm PPIO’s max completion tokens for kimi-k3 from pricing/API docs; if output is still ~131k, drop or correct the override; if context differs, override limit.context instead.
  • [medium] [possible mistake] providers/ppio/models/alibaba/qwen3-235b-a22b-instruct-2507.toml:11 - Check: limit.output should be max completion tokens on this host. Why: Lab output is 16_384 with context 262_144; PPIO sets output = 260_000, nearly the full context window, which is atypical for completion limits and easy to confuse with context. Action: Verify against PPIO model/pricing docs and set the real max output (or context) accordingly.
  • [medium] [possible mistake] providers/ppio/models/alibaba/qwen3.8-2.4t-a95b.toml:6 - Check: Relay reasoning_options must not be [] when the underlying model has documented caller controls this host may still expose. Why: Lab notes for this open twin document reasoning_effort (low/medium/xhigh). The PR only shows thinking.type is rejected; it does not establish that effort is unavailable. Empty options mean no control, not “toggle failed.” Action: Probe whether reasoning_effort is accepted and effective on PPIO; if yes, author the measured effort set (and wire comment); if no, keep [] and state that effort was tested and ignored/rejected.
  • [low] [possible mistake] providers/ppio/provider.toml:12 - Check: Provider header comments should match authored model capabilities. Why: The note “Models not listed above expose no caller control” contradicts many model files (Qwen 3.5/3.6, GLM 4.x/5.x, MiMo, etc.) that set toggle. Action: Update the provider.toml summary so it lists the toggle-only cohort (or drop the blanket “not listed” claim).

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [possible mistake] providers/ppio/models/alibaba/qwen3.8-27b.toml:4 - Check: Relay reasoning_options must follow lab/same-surface peer controls for the model, not a stripped subset. Why: This entry is toggle-only, but same-host qwen3.8-2.4t-a95b and OpenRouter peers author effort low/medium/xhigh for the Qwen3.8 open-weight line. Dropping effort here understates caller control if PPIO accepts reasoning_effort. Action: Probe reasoning_effort on this model; if accepted, set reasoning_options to toggle + ["low", "medium", "xhigh"] (with an Effort wire comment); if rejected, document that explicitly in the header.
  • [medium] [possible mistake] providers/ppio/models/deepseek/deepseek-v3.2.toml:4 - Check: On relays, [] means affirmative no caller control, not “side channel missing / not fully re-tested.” Why: Lab metadata describes hybrid thinking/non-thinking, and OpenRouter peers expose a toggle, but this file uses reasoning_options = [] while notes only that reasoning_content is absent. Missing side channel does not by itself prove toggle is unavailable. Action: Verify whether thinking.type = enabled|disabled turns reasoning on/off for this id; if it does, set { type = "toggle" } (and wire comment); keep [] only with an affirmative no-control note.
  • [medium] [possible mistake] providers/ppio/models/moonshotai/kimi-k2.5.toml:4 - Check: Same relay [] rule vs lab/peer controls. Why: kimi-k2.5 is a reasoner; OpenRouter and other peers expose a toggle, while this file keeps [] and only notes no reasoning_content. Action: Confirm whether thinking.type toggles reasoning on PPIO; set toggle + [interleaved] if the side channel appears when enabled, or keep [] only with measured no-control evidence.
  • [medium] [possible mistake] providers/ppio/models/moonshotai/kimi-k3.toml:17 - Check: Provider [limit] overrides must reflect this host’s real max completion, not a swapped context value. Why: Lab moonshotai/kimi-k3 has limit.output = 131_072 (context 1_048_576). This override sets output = 1_048_576, i.e. max output equal to full context, which is unusual and may be a context/output mix-up. Action: Confirm PPIO’s max completion tokens for kimi-k3; if the lab 131K (or another measured cap) is correct, fix limit.output.
  • [low] [possible mistake] providers/ppio/models/zhipuai/glm-5.toml:18 - Check: Context overrides should match the host catalog, not a near-miss of the lab default. Why: Lab and most hosts use 204_800 for GLM-5; this sets 202_800 (a value seen on some GLM-5 turbo/v variants elsewhere). That is a one-digit-off delta without a stated PPIO source. Action: Verify PPIO’s published context for glm-5 and align to the measured value (likely 204_800 unless PPIO documents 202_800).

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/ppio/models/moonshotai/kimi-k2.6.toml:6 - Check: toggle must not pair with effort that already includes none. Why: Final options are toggle plus effort values that include none (and minimal). Per AGENTS.md / audit skill, when off is an effort value, author effort only — no toggle. Dual controls misrepresent the wire surface and break the none/toggle rule. Action: Drop toggle (and its wire comment), keep effort with the real graded set including none (or document a separate on/off field that is not redundant with none).
  • [high] [violation] providers/ppio/models/xiaomi/mimo-v2.5.toml:6 - Check: toggle must not pair with effort that already includes none. Why: Same dual shape: toggle + ["none", "low", "medium", "high"]. Patch 4 states none turns thinking off, so off is already covered by effort. Action: Use effort-only (with none); remove toggle.
  • [high] [violation] providers/ppio/models/xiaomi/mimo-v2.5-pro.toml:6 - Check: toggle must not pair with effort that already includes none. Why: toggle + full enum including none/minimal. Same rule break as above. Action: Effort-only with verified values; no toggle.
  • [high] [violation] providers/ppio/models/zhipuai/glm-5.1.toml:6 - Check: toggle must not pair with effort that already includes none. Why: toggle + ["none", "minimal", "low", "medium", "high", "xhigh", "max"]. Action: Effort-only (or toggle-only if effort is not a real graded control); never both when none is in effort.
  • [high] [violation] providers/ppio/models/zhipuai/glm-5.2.toml:6 - Check: toggle must not pair with effort that already includes none; baseline = lab effective set. Why: Same dual none+toggle shape. First-party Zhipu/Z.ai GLM-5.2 is effort high|max (aliases map into those); dumping the full schema enum plus toggle invents a control surface the lab does not publish. Action: Remove toggle when none is present; author the effective levels this host actually distinguishes (likely none + high/max, or lab-like high/max if off is not real), not the full enum.
  • [high] [possible mistake] providers/ppio/models/alibaba/qwen3.8-2.4t-a95b.toml:5 - Check: Relays must not use reasoning_options = [] when lab/same-surface peers expose caller control. Why: Lab and OpenRouter peers use always-on thinking with reasoning_effort low|medium|xhigh. Final file sets [] while the header still claims that effort set. Rejecting thinking.type only rules out toggle, not effort. Empty means “no caller control,” not “toggle unavailable.” Action: Restore effort ["low", "medium", "xhigh"] if the host accepts it, or prove effort has no effect and remove the effort comment; do not leave [] with a native-effort claim.
  • [medium] [possible mistake] providers/ppio/models/moonshotai/kimi-k2.5.toml:5 - Check: Effort values must be the host’s real set, not a full-schema dump; baseline is lab/peer toggle-only for K2.5. Why: Options list none|minimal|low|medium|high|xhigh. Lab/established peers are mostly toggle-only. Patch 4 only claims none/minimal off vs low+ on — not that every graded level is distinct. Action: Keep effort-only (shape OK) but shrink values to levels with a meaningful, measured difference (e.g. off vs on, or documented graded set); avoid dumping unused schema tokens.
  • [medium] [possible mistake] providers/ppio/models/deepseek/deepseek-v3.2.toml:5 - Check: [] only when there is affirmative no caller control on this host. Why: Header notes reasoning_effort is accepted but no side channel appears. That does not establish that thinking.type (or another on/off control) is unavailable on a hybrid-reasoning model. Action: Probe toggle (and any real off path); if thinking can be disabled, author toggle (and effort only if graded levels matter); keep [] only if controls truly do nothing.

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/ppio/models/zhipuai/glm-5.1.toml:4 - Check: reasoning_options must match this host’s real controls and must not dump non-distinct effort aliases (AGENTS.md / audit skill: baseline = lab + meaningful effect; never dump the full effort enum). Why: The PR’s own probe says for glm-5.1/5.2, kimi-k2.5/2.6, and mimo-v2.5/pro, none turns thinking off and every graded value turns it on with no ordered difference—yet these files still advertise long ladders (none/low/medium/high/xhigh/max). That invents graded caller control the host does not expose and diverges from lab baselines (glm-5.1/mimo/kimi-k2.x: toggle; glm-5.2: effective high/max). Action: Collapse each of glm-5.1, glm-5.2, kimi-k2.5, kimi-k2.6, mimo-v2.5, and mimo-v2.5-pro to the effective surface only (e.g. lab-style toggle, or effort with none plus the levels that actually change behavior—for glm-5.2 typically none/high/max), and align the leading effort comments with the values you keep.
  • [medium] [possible mistake] providers/ppio/models/deepseek/deepseek-v4-pro.toml:7 - Check: DeepSeek V4 Pro effort baseline is lab/peer-effective levels, not every accepted alias. Why: First-party DeepSeek Pro is high/max (low/medium map to high). These PPIO Pro entries list low/high/max as if low were a distinct grade; if PPIO only accepts low as an alias of high, that overstates control. Action: Verify whether reasoning_effort=low is behaviorally distinct on this host for deepseek-v4-pro and deepseek-v4-pro-0813; if not, drop low and match the lab set high/max (keep Flash’s low/high/max if Flash still treats low as real).
  • [medium] [possible mistake] providers/ppio/models/moonshotai/kimi-k3.toml:17 - Check: Provider [limit].output overrides must reflect this host’s real max output, not context size. Why: Lab moonshotai/kimi-k3 has output = 131_072 and context = 1_048_576; this entry sets output = 1_048_576, which looks like context copied into output and would mislead clients on max completion length. Action: Confirm PPIO’s documented/API max output for kimi-k3; if it is not 1M completion tokens, set limit.output to the real cap (or omit if it matches the lab 131_072).

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [possible mistake] providers/ppio/models/alibaba/qwen3-235b-a22b-instruct-2507.toml:11 - Check: Provider limit overrides must reflect this host’s real context/output caps, not a mislabeled peer value. Why: Lab metadata has limit.output = 16_384 and limit.context = 262_144. This file only sets output = 260_000, which is far above the lab completion cap and matches values other hosts use as context (e.g. scaleway context = 260_000), not max output. That would publish a false 260k completion window. Action: Verify PPIO’s reported max_tokens / context for this model id; if 260k is context, set [limit].context (and keep a real output cap); if output truly differs from the lab, cite the host figure and keep only the real delta.
  • [low] [possible mistake] providers/ppio/provider.toml:15 - Check: Provider header comments must match the final measured model metadata. Why: The comment still says deepseek-v3.2 and kimi-k2.5 return no reasoning side channel, but later commits set both to reasoning_options with toggle and [interleaved] field = "reasoning_content". Stale host notes will mislead the next edit. Action: Update the provider.toml reasoning summary so it matches the final per-model files (side channel + toggle cohorts).

PPIO serves open-weight models through an OpenAI-compatible endpoint at
https://api.ppio.com/openai/v1. This adds the provider with 46 open-weight
models across DeepSeek, MiniMax, Moonshot AI, Qwen, Xiaomi, and Z.ai.

Model ids mirror PPIO's own /openai/v1/models ids so catalog keys match what
the API accepts. Every entry uses base_model and overrides only what differs
from the lab entry: cost, plus limit, modalities, structured_output,
reasoning_options, and interleaved where PPIO reports something different.

Pricing

PPIO lists prices in CNY per million tokens, converted at CNY to USD 6.718405
(2026-09-20, https://open.er-api.com/v6/latest/USD) with the rate, date and
source recorded in each file header. Nine models use context-tiered pricing,
expressed with [[cost.tiers]] and the lowest band as the base cost.

Two models need a note on where a rate applies. glm-4.7 splits its 1-32000
context band by output length, which cost.tiers cannot express, so the
general-case rate is used for that band. glm-4.6v publishes cache_read only
for the 32768+ band.

Reasoning

reasoning_options and interleaved were measured against the live chat API
rather than inferred from documentation, which covers only a curated subset of
models. Each reasoning model was probed with thinking.type enabled and
disabled and with every reasoning_effort level, recording which values are
accepted and whether the thinking state changes.

- Toggle only: the Qwen 3.5, 3.6 and 3.8-27b models, deepseek-v3.2,
  minimax-m3, kimi-k2.5, kimi-k2.6, mimo-v2.5, mimo-v2.5-pro, glm-4.5-air,
  glm-4.5v, glm-4.6, glm-4.6v, glm-4.7, glm-4.7-flash, glm-5, glm-5.1.
- Effort only: qwen3.8-2.4t-a95b, glm-5.2, glm-5.3, glm-5.3-flash.
- Toggle and effort: the DeepSeek V4 family and kimi-k3.
- No caller control: the minimax-m2 family, kimi-k2-thinking, kimi-k2.7-code,
  where thinking.type is accepted but ignored.

Effort lists carry only levels the host distinguishes. reasoning_effort=low is
not behaviourally distinct from high on the DeepSeek V4 family here, so those
entries declare high|max. Where effort includes none alongside graded levels,
the entry carries effort alone with no toggle, since off is already reachable
through effort.

deepseek-v3.2 starts with thinking off, so it is the one model whose toggle
enables rather than disables thinking. Every model that declares a toggle or
an effort carries the exact request field in a top-of-file comment.

Validation

- bun validate passes
- bun run test in packages/sdk passes (23 tests)
@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 Sep 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