feat: add infomaniak provider with 10 models (#2893)

* feat: add infomaniak provider with 10 models

* fix: correct infomaniak reasoning options after live API testing

Verified each reasoning model against the live Infomaniak API:
- reasoning text is returned in `message.reasoning`, so use `interleaved = true`
  instead of the non-existent `field = "reasoning_content"`
- gemma-4-31B-it ignores `reasoning_effort` and never emits reasoning, so drop
  its reasoning_options/interleaved and set `reasoning = false`
- Mistral-Small only accepts `none`/`high`; documented the per-model wire format
  (reasoning_effort on/off) in comments above each reasoning_options

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

* fix: use INFOMANIAK_PRODUCT_ID env var to match Infomaniak API

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

* fix: promote infomaniak Qwen3.5 122B and Gemma 4 31B out of beta

Infomaniak announced that Qwen3.5 (122B), Gemma 4 (31B) and Mistral
Small 4 (119B) are no longer beta and are production-ready. Mistral
Small 4 already had no beta status, so drop `status = "beta"` from the
Qwen3.5 122B and Gemma 4 31B models and bump last_updated.

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

* fix: add required description to standalone infomaniak models

The schema now requires a non-empty `description` on every model. The
six base_model references inherit it from their base model, but the four
standalone models (two embeddings, Ministral 3, Apertus 70B) need their
own. Add descriptions following the repo's existing conventions.

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

* fix: refresh infomaniak pricing, reasoning support, and model identities

Corrects USD pricing to match Infomaniak's CHF-billed rates, fixes reasoning
support flags for gemma-4-31B-it and Mistral-Small (no verified toggle), and
renames models to match their actual upstream identities: MiniLM entry was
mislabeled as the multilingual 117M variant instead of the English-only 33M
one actually served, and Apertus 70B is replaced by the v1.5 release. Also
corrects Kimi-K2.6 modalities (image, no video) and MiniLM's context limit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix: align infomaniak data with live catalog and source every claim

Verified all ten model ids case-by-case against Infomaniak's pricing page,
open-source-models catalog and GET /1/ai/models; all match exactly and are
unchanged.

Data corrections:
- gemma-4-31B-it is served text-only ("Text-to-Text" in both the EN and FR
  catalog), so override attachment=false and modalities.input=["text"] instead
  of inheriting image input from the base model
- bge_multilingual_gemma2 input cap is 8'000, not 8'192 (catalog row and the
  API's own max_token_input)
- drop the unsourced limit.output overrides on Qwen3.5-122B and gemma-4-31B-it
  so both inherit from base_model, matching the Qwen3.5-397B sibling
- Ministral-3-14B release_date 2025-12-15 -> 2025-12-02 (repo majority for this
  model); bge release_date 2024-07-30 -> 2024-07-25 (Hugging Face createdAt)
- provider.toml doc pointed at the French marketing landing page; the schema
  wants a page where models are listed

Claim corrections:
- Mistral-Small-4 claimed the live probe confirmed Infomaniak's docs. It does
  not: the docs say thinking is unsupported, the probe found thinking on by
  default and returned in message.reasoning. Only the reasoning_effort
  parameter itself is unsupported. Pin `mistral3` to the model's transformers
  model_type, which is what makes the exclusion apply.
- MiniLM identity rested on the "based on a Microsoft model" blurb, which does
  not discriminate (both candidates descend from a Microsoft MiniLM). Cite
  Infomaniak's "Parameters 33 M" spec row instead.
- label the two forced limit.output estimates (Apertus, Ministral) as estimates
- note that Nemotron's published 1M input cap exceeds its native window

Per AGENTS.md, move every comment into a single top-of-file block (five files
had reasoning notes below the first key) and add the exact reasoning_effort
wire syntax next to each toggle.

bun validate passes.

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
abonvalle
2026-08-04 20:08:56 +02:00
committed by GitHub
parent 2e3048b62f
commit 83cdfa932c
12 changed files with 379 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
<svg viewBox="0 0 81 80" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M34.5674 13.3333H19.3331V66.6666H34.5674V56.6257L40.1704 51.1686L48.044 66.6666H64.853L50.0947 41.5643L64.0473 28.0308H45.7002L34.5674 40.8367V13.3333Z" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 264 B

@@ -0,0 +1,34 @@
# Model id matches Infomaniak's API model name exactly: `Qwen/Qwen3.5-122B-A10B-FP8`.
# Pricing: Infomaniak bills in CHF; the USD values below are converted at
# 1 CHF = 1.24 USD (mid-market, checked 2026-08-01; live rate 1.2374).
# Infomaniak-listed price: CHF 0.40 input / CHF 3.20 output per 1M tokens.
# Catalog: Image-Text to Text, max input 200'000, not flagged beta.
# Reasoning: toggles reasoning with `reasoning_effort` set to "none" (off) or
# "low"/"medium"/"high" (on) — API: {"reasoning_effort": "none"}. Infomaniak documents the
# field as binary rather than graded effort ("it only allows to enable/disable the thinking:
# `none` disables the thinking, any other value enables the thinking"), and thinking is on by
# default when the field is omitted. Confirmed live on 2026-06-28: response `reasoning` is null
# with "none", populated otherwise. The reasoning text arrives in `message.reasoning`, so
# `interleaved` is set bare — the schema's field enum only covers reasoning_content/
# reasoning_details.
# Sources:
# https://www.infomaniak.com/en/hosting/ai-services/open-source-models
# https://www.infomaniak.com/en/hosting/ai-services/prices
# https://developer.infomaniak.com/docs/api/post/2/ai/{product_id}/openai/v1/chat/completions
base_model = "alibaba/qwen3.5-122b-a10b"
name = "Qwen3.5 122B-A10B FP8"
last_updated = "2026-08-01"
reasoning_options = [{ type = "toggle" }] # API: {"reasoning_effort": "none"} off | "low"|"medium"|"high" on
interleaved = true
[cost]
input = 0.50
output = 3.97
[limit]
context = 200_000
input = 200_000
[modalities]
input = ["text", "image"]
output = ["text"]
@@ -0,0 +1,35 @@
# Model id matches Infomaniak's API model name exactly: `Qwen/Qwen3.5-397B-A17B-FP8`.
# Pricing: Infomaniak bills in CHF; the USD values below are converted at
# 1 CHF = 1.24 USD (mid-market, checked 2026-08-01; live rate 1.2374).
# Infomaniak-listed price: CHF 0.80 input / CHF 3.60 output per 1M tokens.
# Catalog: Image-Text to Text, max input 200'000, flagged Beta.
# Reasoning: toggles reasoning with `reasoning_effort` set to "none" (off) or
# "low"/"medium"/"high" (on) — API: {"reasoning_effort": "none"}. Infomaniak documents the
# field as binary rather than graded effort ("it only allows to enable/disable the thinking:
# `none` disables the thinking, any other value enables the thinking"), and thinking is on by
# default when the field is omitted. Confirmed live on 2026-06-28: response `reasoning` is null
# with "none", populated otherwise. The reasoning text arrives in `message.reasoning`, so
# `interleaved` is set bare — the schema's field enum only covers reasoning_content/
# reasoning_details.
# Sources:
# https://www.infomaniak.com/en/hosting/ai-services/open-source-models
# https://www.infomaniak.com/en/hosting/ai-services/prices
# https://developer.infomaniak.com/docs/api/post/2/ai/{product_id}/openai/v1/chat/completions
base_model = "alibaba/qwen3.5-397b-a17b"
name = "Qwen3.5 397B-A17B FP8"
last_updated = "2026-08-01"
status = "beta"
reasoning_options = [{ type = "toggle" }] # API: {"reasoning_effort": "none"} off | "low"|"medium"|"high" on
interleaved = true
[cost]
input = 0.99
output = 4.46
[limit]
context = 200_000
input = 200_000
[modalities]
input = ["text", "image"]
output = ["text"]
@@ -0,0 +1,37 @@
# Model id matches Infomaniak's API model name exactly: `bge_multilingual_gemma2`
# (snake_case, as used in the /v1/embeddings `model` field and returned by GET /1/ai/models).
# Pricing: Infomaniak bills in CHF; the USD values below are converted at
# 1 CHF = 1.24 USD (mid-market, checked 2026-08-01; live rate 1.2374).
# Infomaniak-listed price: CHF 0.065 input / CHF 0.00 output per 1M tokens.
# Limits: Infomaniak's catalog row gives "Max. input tokens 8'000" (below the 8'192 the upstream
# model supports) and "Dimensions 3584"; `limit.output` carries the embedding dimension, per the
# repo convention for embedding models (cf. providers/openai/models/text-embedding-3-large.toml).
# release_date is BAAI/bge-multilingual-gemma2's Hugging Face creation date.
# Sources:
# https://www.infomaniak.com/en/hosting/ai-services/open-source-models
# https://www.infomaniak.com/en/hosting/ai-services/prices
# https://developer.infomaniak.com/docs/api/post/2/ai/{product_id}/openai/v1/embeddings
# https://huggingface.co/BAAI/bge-multilingual-gemma2
name = "BGE Multilingual Gemma2"
description = "Embedding model for semantic search, retrieval, clustering, and ranking pipelines"
family = "text-embedding"
release_date = "2024-07-25"
last_updated = "2026-08-01"
attachment = false
reasoning = false
temperature = false
tool_call = false
open_weights = true
[cost]
input = 0.08
output = 0.00
[limit]
context = 8_000
input = 8_000
output = 3_584
[modalities]
input = ["text"]
output = ["text"]
@@ -0,0 +1,33 @@
# Model id matches Infomaniak's catalog/pricing string exactly: `google/gemma-4-31B-it`.
# Pricing: Infomaniak bills in CHF; the USD values below are converted at
# 1 CHF = 1.24 USD (mid-market, checked 2026-08-01; live rate 1.2374).
# Infomaniak-listed price: CHF 0.20 input / CHF 0.40 output per 1M tokens.
# Modality: Infomaniak serves this model text-only — the catalog row reads
# "Text-to-Text (optimised for learning)" (EN) / "Text-to-Text (optimisé pour
# l'instruction)" (FR), max input 100'000 — so image input and `attachment` are
# overridden off even though the base model is multimodal.
# Reasoning checked live against the Infomaniak API on 2026-06-28: gemma-4-31B-it ignores
# `reasoning_effort` (none/low/high produce identical output) and never populates
# `message.reasoning` — any step-by-step text stays inline in `content`. The model still
# reasons internally (the API docs say thinking is enabled by default on most models, and
# gemma-4 is not among the listed exceptions, `apertus-ai/Apertus-v1.5-70B` and `mistral3`),
# so `reasoning` stays true (inherited) with no verified control -> `reasoning_options = []`.
# Sources:
# https://www.infomaniak.com/en/hosting/ai-services/open-source-models
# https://www.infomaniak.com/en/hosting/ai-services/prices
# https://developer.infomaniak.com/docs/api/post/2/ai/{product_id}/openai/v1/chat/completions
base_model = "google/gemma-4-31b-it"
last_updated = "2026-08-01"
attachment = false
reasoning_options = []
[cost]
input = 0.25
output = 0.50
[limit]
context = 100_000
input = 100_000
[modalities]
input = ["text"]
@@ -0,0 +1,39 @@
# Model id matches Infomaniak's API model name exactly: `mini_lm_l12_v2`
# (snake_case; Infomaniak's display label is "All MiniLM L12 v2").
# Identity corrected 2026-08-01: this is sentence-transformers/all-MiniLM-L12-v2, not
# sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2, which this entry was previously named
# after. The decisive evidence is Infomaniak's own spec row — "Parameters 33 M" — which matches
# all-MiniLM-L12-v2 (33.36M) and rules out the multilingual variant (117.65M). Dimensions (384) and
# max sequence length (128) are identical across both, so they cannot discriminate. Neither can the
# catalog blurb about "a model published by Microsoft": both descend from a Microsoft MiniLM.
# Limits: Infomaniak's catalog row gives max input 128 and Dimensions 384; `limit.output` carries
# the embedding dimension, per the repo convention for embedding models
# (cf. providers/digitalocean/models/all-mini-lm-l6-v2.toml).
# Pricing: free on Infomaniak (the pricing page lists "Free" for this model).
# Sources:
# https://huggingface.co/sentence-transformers/all-MiniLM-L12-v2
# https://www.infomaniak.com/en/hosting/ai-services/open-source-models
# https://www.infomaniak.com/en/hosting/ai-services/prices
name = "All-MiniLM-L12-v2"
description = "Embedding model for semantic search, retrieval, clustering, and ranking pipelines"
family = "text-embedding"
release_date = "2021-08-30"
last_updated = "2026-08-01"
attachment = false
reasoning = false
temperature = false
tool_call = false
open_weights = true
[cost]
input = 0.00
output = 0.00
[limit]
context = 128
input = 128
output = 384
[modalities]
input = ["text"]
output = ["text"]
@@ -0,0 +1,44 @@
# Model id matches Infomaniak's API model name exactly: `mistralai/Ministral-3-14B-Instruct-2512`.
# Defined inline (no `base_model`) because models/ has no ministral-3-14b metadata entry.
# Pricing: Infomaniak bills in CHF; the USD values below are converted at
# 1 CHF = 1.24 USD (mid-market, checked 2026-08-01; live rate 1.2374).
# Infomaniak-listed price: CHF 0.30 input / CHF 0.40 output per 1M tokens.
# Catalog: Image-Text to Text, max input 100'000, flagged Beta.
# Reasoning: `reasoning = false`. Infomaniak's chat/completions docs list `mistral3` among the
# models that do not support `reasoning_effort`, and `mistral3` is this model's transformers
# `model_type` (HF config). All five other provider entries for Ministral 3 14B in this repo
# (openrouter, kilo, nvidia, nano-gpt, digitalocean) also declare `reasoning = false`.
# limit.output = 25_600 is an estimate: Infomaniak publishes only a max *input* cap, and the
# schema requires limit.output on provider models that have no models/ base entry.
# release_date follows the repo's majority for this model (2025-12-02, used by openrouter,
# kilo and nano-gpt); HF createdAt is 2025-10-31 (pre-release repo creation).
# Sources:
# https://www.infomaniak.com/en/hosting/ai-services/open-source-models
# https://www.infomaniak.com/en/hosting/ai-services/prices
# https://developer.infomaniak.com/docs/api/post/2/ai/{product_id}/openai/v1/chat/completions
# https://huggingface.co/mistralai/Ministral-3-14B-Instruct-2512
name = "Ministral 3 14B Instruct"
description = "Compact Mistral model for edge, latency-sensitive, and cost-efficient workloads"
family = "ministral"
release_date = "2025-12-02"
last_updated = "2026-08-01"
status = "beta"
attachment = true
reasoning = false
temperature = true
tool_call = true
structured_output = true
open_weights = true
[cost]
input = 0.37
output = 0.50
[limit]
context = 100_000
input = 100_000
output = 25_600
[modalities]
input = ["text", "image"]
output = ["text"]
@@ -0,0 +1,32 @@
# Model id matches Infomaniak's API model name exactly: `mistralai/Mistral-Small-4-119B-2603`.
# Pricing: Infomaniak bills in CHF; the USD values below are converted at
# 1 CHF = 1.24 USD (mid-market, checked 2026-08-01; live rate 1.2374).
# Infomaniak-listed price: CHF 0.20 input / CHF 0.75 output per 1M tokens.
# Catalog: Image-Text to Text, max input 256'000, not flagged beta.
# Reasoning: no verified control, hence `reasoning_options = []` (not a toggle).
# Live probe 2026-06-28: an explicit {"reasoning_effort": "none"} 400s server-side
# ("chat_template is not supported for Mistral tokenizers"), and omitting the field leaves
# thinking on by default — there is no reachable "off" state, so claiming a toggle would be false.
# Infomaniak's docs list `mistral3` among the models that do not support `reasoning_effort`;
# `mistral3` is this model's transformers `model_type` (HF config), so the doc and the 400 agree
# that the *parameter* is unsupported here. They do not agree on the rest: the doc phrases it as
# thinking being unsupported, whereas the probe shows thinking runs by default and its output is
# returned in `message.reasoning`. The observed behaviour is what is encoded — `reasoning`
# (inherited true) plus bare `interleaved`, with no reasoning_options.
# Sources:
# https://www.infomaniak.com/en/hosting/ai-services/open-source-models
# https://www.infomaniak.com/en/hosting/ai-services/prices
# https://developer.infomaniak.com/docs/api/post/2/ai/{product_id}/openai/v1/chat/completions
# https://huggingface.co/mistralai/Mistral-Small-4-119B-2603 (config.json "model_type": "mistral3")
base_model = "mistral/mistral-small-2603"
last_updated = "2026-08-01"
reasoning_options = []
interleaved = true
[cost]
input = 0.25
output = 0.93
[limit]
context = 256_000
input = 256_000
@@ -0,0 +1,36 @@
# Model id matches Infomaniak's API model name exactly: `moonshotai/Kimi-K2.6`.
# Pricing: Infomaniak bills in CHF; the USD values below are converted at
# 1 CHF = 1.24 USD (mid-market, checked 2026-08-01; live rate 1.2374).
# Infomaniak-listed price: CHF 0.60 input / CHF 3.00 output per 1M tokens.
# Catalog: Image-Text to Text (no video, unlike the moonshotai/kimi-k2.6 base entry),
# max input 256'000, flagged Beta.
# Reasoning: toggles reasoning with `reasoning_effort` set to "none" (off) or
# "low"/"medium"/"high" (on) — API: {"reasoning_effort": "none"}. Infomaniak documents the
# field as binary rather than graded effort ("it only allows to enable/disable the thinking:
# `none` disables the thinking, any other value enables the thinking"), and thinking is on by
# default when the field is omitted. Confirmed live on 2026-06-28: response `reasoning` is null
# with "none", populated otherwise. The reasoning text arrives in `message.reasoning`, so
# `interleaved` is set bare — the schema's field enum only covers reasoning_content/
# reasoning_details.
# Sources:
# https://www.infomaniak.com/en/hosting/ai-services/open-source-models
# https://www.infomaniak.com/en/hosting/ai-services/prices
# https://developer.infomaniak.com/docs/api/post/2/ai/{product_id}/openai/v1/chat/completions
base_model = "moonshotai/kimi-k2.6"
last_updated = "2026-08-01"
status = "beta"
reasoning_options = [{ type = "toggle" }] # API: {"reasoning_effort": "none"} off | "low"|"medium"|"high" on
interleaved = true
[cost]
input = 0.74
output = 3.72
[limit]
context = 256_000
input = 256_000
output = 256_000
[modalities]
input = ["text", "image"]
output = ["text"]
@@ -0,0 +1,33 @@
# Model id matches Infomaniak's API model name exactly: `nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-FP8`.
# Pricing: Infomaniak bills in CHF; the USD values below are converted at
# 1 CHF = 1.24 USD (mid-market, checked 2026-08-01; live rate 1.2374).
# Infomaniak-listed price: CHF 0.05 input / CHF 0.20 output per 1M tokens.
# Catalog: Text to Text, max input 1'000'000, flagged Beta. That 1M figure is Infomaniak's own
# published cap and is transcribed as-is; note it exceeds the model's native 262'144 window
# (models/nvidia/nemotron-3-nano-30b-a3b.toml) — it is not a typo on our side.
# Reasoning: toggles reasoning with `reasoning_effort` set to "none" (off) or
# "low"/"medium"/"high" (on) — API: {"reasoning_effort": "none"}. Infomaniak documents the
# field as binary rather than graded effort ("it only allows to enable/disable the thinking:
# `none` disables the thinking, any other value enables the thinking"), and thinking is on by
# default when the field is omitted. Confirmed live on 2026-06-28: response `reasoning` is null
# with "none", populated otherwise. The reasoning text arrives in `message.reasoning`, so
# `interleaved` is set bare — the schema's field enum only covers reasoning_content/
# reasoning_details.
# Sources:
# https://www.infomaniak.com/en/hosting/ai-services/open-source-models
# https://www.infomaniak.com/en/hosting/ai-services/prices
# https://developer.infomaniak.com/docs/api/post/2/ai/{product_id}/openai/v1/chat/completions
base_model = "nvidia/nemotron-3-nano-30b-a3b"
name = "Nemotron 3 Nano 30B A3B FP8"
last_updated = "2026-08-01"
status = "beta"
reasoning_options = [{ type = "toggle" }] # API: {"reasoning_effort": "none"} off | "low"|"medium"|"high" on
interleaved = true
[cost]
input = 0.06
output = 0.25
[limit]
context = 1_000_000
input = 1_000_000
@@ -0,0 +1,48 @@
# Model id matches Infomaniak's catalog/pricing string exactly: `swiss-ai/Apertus-v1.5-70B`
# (both the EN and FR product pages spell it this way; the `apertus-ai/...` form that appears in
# the chat/completions `reasoning_effort` docs is a typo — Infomaniak's GET /1/ai/models has
# always used the `swiss-ai/` prefix for this family, though that endpoint is auth-gated and was
# not queried for v1.5 here).
# Defined inline (no `base_model`) because models/ has no swiss-ai metadata entry.
# Pricing: Infomaniak bills in CHF; the USD values below are converted at
# 1 CHF = 1.24 USD (mid-market, checked 2026-08-01; live rate 1.2374).
# Infomaniak-listed price: CHF 0.70 input / CHF 2.50 output per 1M tokens.
# Catalog: Image-Audio-Text to Text, max input 100'000 (the upstream model goes to 262'144;
# Infomaniak serves the smaller window), flagged Beta.
# Reasoning: `reasoning = false` here, unlike gemma-4-31B-it and Mistral-Small-4 which keep
# `reasoning = true` with `reasoning_options = []`. The difference is the default, not the
# absence of a toggle: Apertus 1.5 is opt-in thinking upstream ("Pass `enable_thinking=True` to
# `apply_chat_template` to activate it"), and Infomaniak names this model as one that does not
# support `reasoning_effort` at all — so there is no way to switch thinking ON through their
# OpenAI-compatible API and the model as served never emits reasoning. Gemma, by contrast, is
# not in that exclusion list and thinking is on by default there.
# limit.output = 8_192 is an estimate: Infomaniak publishes only a max *input* cap, and the
# schema requires limit.output on provider models that have no models/ base entry.
# Sources:
# https://www.infomaniak.com/en/hosting/ai-services/open-source-models
# https://www.infomaniak.com/en/hosting/ai-services/prices
# https://developer.infomaniak.com/docs/api/post/2/ai/{product_id}/openai/v1/chat/completions
# https://huggingface.co/swiss-ai/Apertus-v1.5-70B
name = "Apertus v1.5 70B"
description = "Open, ethically-sourced Swiss AI model for multilingual, multimodal chat and instruction following"
release_date = "2026-07-24"
last_updated = "2026-08-01"
attachment = true
reasoning = false
temperature = true
tool_call = true
open_weights = true
status = "beta"
[cost]
input = 0.87
output = 3.10
[limit]
context = 100_000
input = 100_000
output = 8_192
[modalities]
input = ["text", "image", "audio"]
output = ["text"]
+5
View File
@@ -0,0 +1,5 @@
name = "Infomaniak"
npm = "@ai-sdk/openai-compatible"
api = "https://api.infomaniak.com/2/ai/${INFOMANIAK_PRODUCT_ID}/openai/v1"
env = ["INFOMANIAK_API_KEY", "INFOMANIAK_PRODUCT_ID"]
doc = "https://www.infomaniak.com/en/hosting/ai-services/open-source-models"