Skip to content

Add AI/ML API provider - #6189

Open
hugoaimlapi wants to merge 5 commits into
anomalyco:devfrom
aimlapi:dev
Open

Add AI/ML API provider#6189
hugoaimlapi wants to merge 5 commits into
anomalyco:devfrom
aimlapi:dev

Conversation

@hugoaimlapi

@hugoaimlapi hugoaimlapi commented Sep 3, 2026

Copy link
Copy Markdown

Adds AI/ML API — an OpenAI-compatible multi-model gateway — with a catalog sync module.

  • providers/aimlapi/: provider.toml (npm = "@ai-sdk/openai-compatible", api = "https://api.aimlapi.com/v1", env = ["AIMLAPI_API_KEY"]), logo.svg (currentColor, square viewBox), and 108 chat models
  • packages/core/src/sync/providers/aimlapi.ts + bun aimlapi:sync: syncs from the public catalog (GET /v1/models?include=pricing,modalities, no key required). Only openai/chat-completions entries with text-only output are imported
  • Every model references its lab entry via base_model; provider files are override-only — cost, host limits where they differ, and reasoning_options read per model from the API's published request schema
  • Costs converted to USD per MTok from the catalog's per-N-token pricing (provided/generated/cachedinput/output/cache_read)
  • Catalog models with no lab entry under models/, and reasoning models where the API exposes no reasoning control, are skipped rather than guessed

Docs: https://docs.aimlapi.com · Pricing: https://aimlapi.com/pricing

Lookov and others added 4 commits September 1, 2026 16:32
AI/ML API is an aggregator exposing many creators' models behind one
OpenAI-compatible key, so it gets a sync provider rather than a
hand-written model set.

The public catalog needs no key. Only entries served as
openai/chat-completions are taken, and of those only the ones whose
output is purely text — an id can appear under several endpoint types,
and its image or audio surface is a different product.

Pricing is quoted as price-per-N-tokens and keyed by origin (provided /
generated / cached), which maps onto input / output / cache_read.

163 of the 338 text-output chat models are published here. The rest are
skipped by skippedNotice because the catalog does not yet expose a
description or an output limit for them; inventing either would be worse
than an absent entry. deleteMissing is off since the catalog lists far
more than the chat surface, so one response omitting a model is not
proof it is gone.

Capability flags the catalog does not report (reasoning, tool_call,
structured_output, open_weights) keep any value already in the repo
instead of being overwritten with a guess.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add AI/ML API provider with catalog sync
…ng them

AI/ML API hosts other people's models and authors none of them, so every
entry has to point at the lab file. AGENTS.md makes that a blocker
("Non-lab hosts use base_model"), and the previous full inlines both
violated it and drifted from the repository's own data: 65 models
disagreed with their lab entry on reasoning, 75 on tool_call, 37 on
structured_output, 17 on attachment. openai/gpt-5 shipped here as
reasoning = false, tool_call = false while models/openai/gpt-5.toml says
both are true.

The cause was a fallback of the shape `existing?.reasoning ?? false`.
`existing` only ever reads this provider's own directory, which does not
exist for a new provider, so the guard never applied and every model was
written as false. The entries now carry no capability flags at all, so
there is nothing left to contradict.

What a file states is now only what is genuinely ours: cost, a limit when
it differs from the base, and reasoning_options. The limit no longer sets
`input`, because the catalog publishes a context window and an output cap
but no input cap, and equating input with the whole context overwrote the
lab's correct split (272k in + 128k out inside a 400k window).

reasoning_options is required whenever the base reasons, and no lab entry
carries it (0 of 245). It is read per model from the API's own published
request schema at /docs-json, so the declared control is the one the
endpoint actually accepts rather than an assumption.

Coverage is 108 of the 338 text-output chat models. 192 are skipped
because this repository has no lab entry to point at — authoring complete
lab files for them would mean sourcing capability metadata the catalog
does not publish — and 38 because their base reasons but the API does not
document the control. Both groups are reported through skippedNotice.

Verified: bun run validate exits 0 and resolves aimlapi/openai/gpt-5 to
reasoning = true, tool_call = true and the lab limit split, with our
price. bun test is 268 pass / 4 fail, the same four failures a pristine
tree produces. Re-running the sync reports 108 unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reference lab entries with base_model instead of inlining them
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] packages/core/src/sync/providers/aimlapi.ts:227 - Check: Relay reasoning_options must follow lab + same-surface peer baselines (AGENTS.md → Reasoning options). Why: The sync only scrapes a reasoning_effort enum and writes effort for every reasoner. The authored catalog is almost entirely identical ["none", "low", "medium", "high"], which contradicts first-party and peer controls (e.g. DeepSeek V4 is toggle + high/max or peer high/xhigh; Qwen3.8 2.4T A95B is always-on with low/medium/xhigh; Claude Opus 4.8 is low/medium/high/xhigh/max (± toggle); GPT-5 is minimal/low/medium/high; Kimi K2 Thinking peers use []). This invents GPT-style L/M/H and ignores toggle/budget surfaces. Action: Derive options from first-party lab entries and established same-surface peers (Eden AI’s lab/OpenRouter mapping is the right pattern). Author only controls this host actually exposes; use [] for always-on; do not invent L/M/H when lab/peers are narrower or different; add toggle/budget when that is the real wire control.
  • [high] [violation] providers/aimlapi/models/deepseek/deepseek-v4-pro.toml:5 - Check: DeepSeek V4 relay reasoning controls. Why: Authored as effort = ["none", "low", "medium", "high"]. Lab providers/deepseek/models/deepseek-v4-pro.toml is toggle + high/max; OpenRouter peer is toggle + high/xhigh. Same wrong shape on deepseek-v4-flash, deepseek-v4-flash-vision-exp, and deepseek-v4-pro-0813. Action: Replace with this host’s real DeepSeek V4 control set (or skip until documented); do not publish L/M/H/none for these IDs.
  • [high] [violation] providers/aimlapi/models/alibaba/qwen3.8-2.4t-a95b.toml:5 - Check: Always-on / non-GPT Qwen reasoning options. Why: Lab metadata and OpenRouter both treat this as mandatory reasoning with low/medium/xhigh (no none). This file publishes none/low/medium/high. Related Qwen reasoners (e.g. 3.5/3.7/3.8 family) are also forced into L/M/H instead of lab toggle+budget or peer effort sets. Action: Match lab/peer option sets per model; use [] when reasoning is always on with no off control.
  • [high] [violation] providers/aimlapi/models/google/gemini-2.5-flash-image.toml:1 - Check: Chat catalog must not import image-generation surfaces; text-only output filter. Why: Sync claims only openai/chat-completions with pure text output, but several Nano Banana / image IDs are imported (gemini-2.5-flash-image, gemini-3-pro-image, gemini-3-pro-image-preview, gemini-3.1-flash-image*, etc.). Lab entries have output = ["text", "image"], so merge yields image-output chat models plus invented reasoning_options. OpenRouter’s peer for gemini-2.5-flash-image sets reasoning = false and does not treat it as a normal reasoner. Action: Exclude image-generation IDs (or require a real text-only output override and drop bogus reasoning_options). Fix isChatTextModel so AIML catalog modality noise cannot reintroduce them.
  • [medium] [violation] providers/aimlapi/models/openai/gpt-5.toml:5 - Check: GPT-family effort lists must match native/peer sets, not a fixed quadruple. Why: GPT-5 is authored as none/low/medium/high; OpenAI and OpenRouter use minimal/low/medium/high. GPT-5.6 Luna/Sol/Terra peers include xhigh/max where applicable; Claude Opus 4.7/4.8 peers use xhigh/max (± toggle), not none+L/M/H. Action: After fixing the sync mapper, regenerate GPT/Claude (and other) entries from documented host enums intersected with lab/peer baselines.
  • [medium] [possible mistake] providers/aimlapi/models/moonshotai/kimi-k2-thinking.toml:5 - Check: Always-on thinking model controls. Why: OpenRouter peer uses reasoning_options = [] for moonshotai/kimi-k2-thinking. This PR publishes graded none/low/medium/high, which implies caller off/effort control the peer does not. Action: Verify AIML’s actual request schema; if no control exists, use [] or skip the model rather than inventing effort levels.

… from per-model schemas

Addresses the review on this PR. Two separate causes, one in this sync and one
upstream in the host's API.

Image surfaces. `isChatTextModel` judged each record on its own modalities, but
the catalog lists an id once per endpoint type and the CHAT record of an image
model claims text output: `google/gemini-2.5-flash-image` appears both as
`openai/image-generations` with `output = ["image"]` and as
`openai/chat-completions` with `output = ["text"]`, and the same holds for the
`gemini-3-pro-image` and `gemini-3.1-flash-image` families. The answer is not in
the record, so the whole response is indexed first and an id this host serves on
any media surface is refused regardless of what its chat record claims. The six
image entries this admitted are deleted; `deleteMissing: false` retains files that
merely fall out of the source, which is why removing them takes an explicit
delete.

Reasoning options. The uniform `["none", "low", "medium", "high"]` was not
invented here — it was read faithfully from a host schema that published one
boilerplate enum for every model. The host has since corrected that, and its
published schemas now carry seven distinct ladders. Re-running the sync therefore
produces per-model values: `none` disappears from GPT-5, Qwen3.8 2.4T A95B and
Kimi K2 Thinking, and two models that previously documented no control at all
(`alibaba/qwen3.6-max-preview`, `z-ai/glm-5.3-flash`) now do.

Known remaining gap, stated rather than papered over: the host's per-model schema
endpoint still understates GPT-5, publishing `low/medium/high` where the model
demonstrably accepts `minimal` as well. That is a fix on the host side, not here;
until it lands, this sync can only publish what the per-model schema states.
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] packages/core/src/sync/providers/aimlapi.ts:6227 - Check: Relay reasoning_options must follow lab + same-surface peers for that model (AGENTS.md / audit-reasoning-options), not a generic GPT ladder. Why: DeepSeek V4 entries still ship effort = ["none","low","medium","high"] (e.g. providers/aimlapi/models/deepseek/deepseek-v4-pro.toml). First-party DeepSeek is toggle + high/max (Flash: low/high/max); OpenRouter peers use toggle + high/xhigh. Forcing L/M/H onto DeepSeek V4 is an explicit anti-pattern and mis-describes caller controls on this host. Action: Re-derive DeepSeek (and any other non-GPT reasoners still on that ladder) from lab/peer baselines intersected with what aimlapi actually accepts; stop emitting invent L/M/H for V4.
  • [high] [violation] packages/core/src/sync/providers/aimlapi.ts:6101 - Check: Discover the full host reasoning surface (toggle, effort, budget_tokens), not only reasoning_effort. Why: fetchReasoningEffort / findReasoningEffortEnum only walk for reasoning_effort.enum and always emit a single effort option. Lab and peers for Qwen3.5/3.8 use toggle + budget_tokens (and/or non-L/M/H effort); Gemini 2.5 Flash-Lite is toggle + budget_tokens (OpenRouter: toggle-only); aimlapi writes effort ladders instead (e.g. gemini-2.5-flash-liteminimal/low/medium/high/max). That systematically mis-models controls this OpenAI-compatible path may expose as enable_thinking / thinking_budget / similar. Action: Parse toggle and budget fields from the per-model schema (or map from lab/peer when the host is a thin pass-through); emit the matching option shapes and leading wire comments for every toggle.
  • [high] [possible mistake] packages/core/src/sync/providers/aimlapi.ts:6123 - Check: Per-model schema resolution must not pick the first reasoning_effort enum in the whole docs tree. Why: findReasoningEffortEnum DFS-returns the first reasoning_effort.enum anywhere in /docs-json. Patch 3 already had to undo a host-wide boilerplate none/low/medium/high; most Claude/Qwen/DeepSeek/Seed files were left on that set while only a subset was regenerated. First-match search makes residual shared defaults easy to reintroduce and hard to notice. Action: Bind the enum to the chat-completions request body for that model id (or otherwise disambiguate model-specific vs global schema), re-sync, and diff every reasoning model against the corrected source.
  • [medium] [possible mistake] providers/aimlapi/models/anthropic/claude-sonnet-4.6.toml:5 - Check: Claude effort sets on relays should match lab/peer graded levels. Why: Aimlapi uses ["none","low","medium","high"] for Sonnet 4.6 / Opus 4.x / Haiku 4.5. Anthropic lab Sonnet 4.6 is low/medium/high/max (Opus 4.8 adds xhigh); OpenRouter Sonnet 4.6 is toggle + low/medium/high/max. Missing max/xhigh and a blanket none look like the old shared ladder, not Claude’s surface. Action: Verify aimlapi’s real Claude effort (and off) wire values; align each Claude entry to lab/peer levels the host actually forwards.
  • [medium] [possible mistake] providers/aimlapi/models/openai/gpt-5.toml:5 - Check: GPT effort lists should include lab/peer levels the host accepts. Why: Final gpt-5 (and several GPT-5.x / codex / pro rows) is low/medium/high only. OpenAI and OpenRouter GPT-5 use minimal/low/medium/high; GPT-5.4 Pro lab is medium/high/xhigh, while aimlapi still has low/medium/high. The PR itself notes the host schema understates GPT-5. Action: Confirm live accepted efforts per id; restore minimal/xhigh (and drop spurious low/none) where the API accepts them, or skip until the host schema is fixed rather than publishing a known-wrong subset.
  • [medium] [possible mistake] providers/aimlapi/models/openai/o1.toml:5 - Check: Do not add effort levels beyond lab/peers without host evidence. Why: Final o1 and o3-mini list xhigh, but first-party OpenAI entries are only low/medium/high. Extra levels need host docs or a demonstrated effect. Action: Prove xhigh on aimlapi for these ids or remove it.
  • [low] [possible mistake] .pr-review/pull-request.json:4 - Check: Material catalog data should cite what each source supports. Why: Body links docs/pricing generally but does not map claims (per-model costs, limit overrides, which schema field backs each reasoning ladder). That blocks review of the many non-round USD/MTok figures and limit deltas. Action: Add brief claim→source notes (catalog pricing units, docs-json control field, any limit overrides) in the PR body or leading TOML headers.

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.

3 participants