diff --git a/models/jaredpalmer/kev-4b.toml b/models/jaredpalmer/kev-4b.toml new file mode 100644 index 00000000000..ceb8e062db8 --- /dev/null +++ b/models/jaredpalmer/kev-4b.toml @@ -0,0 +1,41 @@ +# Source: https://huggingface.co/jaredpalmer/kev-4b (model card, accessed 2026-10-20). +# Kev 1.0, first published 2026-09-24: a LoRA adapter and pointer head on Qwen3.5-4B-Base that +# returns a probability per option and generates no text, so output is 0. States of up to +# 65,536 tokens are served; the card validates accuracy to 8,192. English only. +schema = 2 +v2_only = true +type = "decision" +name = "Kev 4B" +description = "Jared Palmer's open-weight 4B decision model that returns calibrated probabilities for typed choice, score and yes/no questions about a text or JSON state" +open_weights = true +release_date = "2026-09-24" +license = "Apache-2.0" + +[modalities] +input = ["text"] +output = ["decision"] + +[capabilities] +tools = { supported = false } +reasoning = { supported = false } +temperature = false +top_p = false +top_k = false + +[limit] +context = 65_536 +output = 0 + +[[links]] +label = "Model card" +url = "https://huggingface.co/jaredpalmer/kev-4b" +type = "model_card" + +[[links]] +label = "Source code" +url = "https://github.com/jaredpalmer/kev" +type = "other" + +[[weights]] +label = "Hugging Face" +url = "https://huggingface.co/jaredpalmer/kev-4b" diff --git a/models/vllm-sr/d3-mini.toml b/models/vllm-sr/d3-mini.toml new file mode 100644 index 00000000000..cdfd69f3691 --- /dev/null +++ b/models/vllm-sr/d3-mini.toml @@ -0,0 +1,34 @@ +# Source: https://huggingface.co/vllm-sr/d3-mini (model card, config.json, decision_config.json; accessed +# 2026-10-21). Decision 3.0 from vLLM Semantic Router: a fine-tune of Qwen3.5-4B (4.54B parameters with a +# 0.33B vision encoder) that returns a probability per option and generates no text, so output is 0. +# Context: decision_config.json sets max_length = null, so the vLLM-SR runtime serves max_position_embeddings, +# 262,144 (vllm-project/semantic-router src/model-runtime/vllm_srun/families/decision3/package.py). +# Tag v3.0.0 was pushed on 2026-10-10 and the current weights, v3.1.0, on 2026-10-11. +schema = 2 +v2_only = true +type = "decision" +name = "d3-mini" +description = "vLLM Semantic Router 4B decision model that answers typed choice, yes/no and score questions about text, images or video with probabilities" +open_weights = true +release_date = "2026-10-10" +last_updated = "2026-10-11" +license = "Apache-2.0" + +[modalities] +input = ["text", "image", "video"] +output = ["decision"] + +[capabilities] +tools = { supported = false } +reasoning = { supported = false } +temperature = false +top_p = false +top_k = false + +[limit] +context = 262_144 +output = 0 + +[[weights]] +label = "Hugging Face" +url = "https://huggingface.co/vllm-sr/d3-mini" diff --git a/packages/core/src/generate.ts b/packages/core/src/generate.ts index f59f6f6efba..5c60b261d47 100755 --- a/packages/core/src/generate.ts +++ b/packages/core/src/generate.ts @@ -135,6 +135,7 @@ async function generateProviders( cause: { providerPath }, }); } + let v2OnlyCount = 0; for await (const modelPath of new Bun.Glob("**/*.toml").scan({ cwd: modelsPath, absolute: true, @@ -148,7 +149,10 @@ async function generateProviders( }).then((mod) => mod.default); raw.id = modelID; // Models marked `v2_only = true` are only published in the v2 API. - if (raw.v2_only === true) continue; + if (raw.v2_only === true) { + v2OnlyCount++; + continue; + } const toml = modelV2ToV1(raw, { modelPath }, provider.data.npm); if (toml.base_model !== undefined) { const baseModel = BaseModel.safeParse(toml); @@ -177,6 +181,8 @@ async function generateProviders( provider.data.models[modelID] = normalizeModelCost(model.data); } if (Object.keys(provider.data.models).length === 0) { + // A provider that serves only v2_only models is left out of v1. + if (v2OnlyCount > 0) continue; throw new Error(`Provider "${providerID}" has no models`, { cause: { providerPath }, }); diff --git a/packages/core/test/generate.test.ts b/packages/core/test/generate.test.ts index 02f1a17b09d..e7fb828be1b 100644 --- a/packages/core/test/generate.test.ts +++ b/packages/core/test/generate.test.ts @@ -45,6 +45,51 @@ describe("catalog generation", () => { }); }); + test("leaves providers with only v2_only models out of v1", async () => { + await withFixture(async (root) => { + await write(root, "providers/decider/provider.toml", providerToml("Decider")); + await write( + root, + "providers/decider/models/decide.toml", + `schema = 2 +v2_only = true +type = "decision" +name = "Decide" +description = "Example decision model that only the v2 catalog publishes" +open_weights = true +release_date = "2026-01-02" + +[modalities] +input = ["text"] +output = ["decision"] + +[capabilities] +tools = { supported = false } +reasoning = { supported = false } +temperature = false +top_p = false +top_k = false + +[limit] +context = 8_192 +output = 0 + +[cost.text.input] +price = 1 + +[cost.text.output] +price = 0 +`, + ); + + const providers = await generate(path.join(root, "providers")); + expect(providers.decider).toBeUndefined(); + + const providersV2 = await generateV2(path.join(root, "providers")); + expect(Object.keys(providersV2.decider?.models ?? {})).toEqual(["decide"]); + }); + }); + test("base_model publishes canonical identity with the provider model", async () => { await withFixture(async (root) => { await write(root, "providers/direct/provider.toml", providerToml("Direct")); diff --git a/providers/verathos/logo.svg b/providers/verathos/logo.svg new file mode 100644 index 00000000000..fd8d0577b6b --- /dev/null +++ b/providers/verathos/logo.svg @@ -0,0 +1 @@ + diff --git a/providers/verathos/models/clef-flash.toml b/providers/verathos/models/clef-flash.toml new file mode 100644 index 00000000000..f08e5f3878a --- /dev/null +++ b/providers/verathos/models/clef-flash.toml @@ -0,0 +1,22 @@ +# Price and limits: https://api.verathos.ai/v1/models (2026-10-20). Billed on input tokens only, so +# output is 0. Serving: POST /v1/systemone, which caps the state at 65,536 tokens (max_state_tokens) +# and takes up to 4 PNG, JPEG or WebP images. System One has no temperature parameter. +schema = 2 +v2_only = true +base_model = "cloudflare/clef-flash" + +[capabilities] +temperature = false + +[limit] +context = 65_536 + +[api.systemone] +base_url = "https://api.verathos.ai/v1" +sdk = { aisdk = "@ai-sdk/typesafe-ai", opencodeai = "@opencode/ai/providers/typesafe-ai" } + +[cost.text.input] +price = 0.02 + +[cost.text.output] +price = 0 diff --git a/providers/verathos/models/d3-flash.toml b/providers/verathos/models/d3-flash.toml new file mode 100644 index 00000000000..831f4125838 --- /dev/null +++ b/providers/verathos/models/d3-flash.toml @@ -0,0 +1,23 @@ +# Price and limits: https://api.verathos.ai/v1/models (2026-10-20). Billed on input tokens only, so +# output is 0. Serving: POST /v1/systemone with max_state_tokens 16,384; input_modalities is text +# only and a request with images gets 400, so this entry is text only. +schema = 2 +v2_only = true +base_model = "vllm-sr/d3-flash" + +[modalities] +input = ["text"] +output = ["decision"] + +[limit] +context = 16_384 + +[api.systemone] +base_url = "https://api.verathos.ai/v1" +sdk = { aisdk = "@ai-sdk/typesafe-ai", opencodeai = "@opencode/ai/providers/typesafe-ai" } + +[cost.text.input] +price = 0.02 + +[cost.text.output] +price = 0 diff --git a/providers/verathos/models/d3-mini.toml b/providers/verathos/models/d3-mini.toml new file mode 100644 index 00000000000..ecb193f6366 --- /dev/null +++ b/providers/verathos/models/d3-mini.toml @@ -0,0 +1,23 @@ +# Price and limits: https://api.verathos.ai/v1/models (2026-10-20). Billed on input tokens only, so +# output is 0. Serving: POST /v1/systemone with max_state_tokens 16,384; input_modalities is text +# only and a request with images gets 400, so this entry is text only. +schema = 2 +v2_only = true +base_model = "vllm-sr/d3-mini" + +[modalities] +input = ["text"] +output = ["decision"] + +[limit] +context = 16_384 + +[api.systemone] +base_url = "https://api.verathos.ai/v1" +sdk = { aisdk = "@ai-sdk/typesafe-ai", opencodeai = "@opencode/ai/providers/typesafe-ai" } + +[cost.text.input] +price = 0.015 + +[cost.text.output] +price = 0 diff --git a/providers/verathos/models/kev-4b.toml b/providers/verathos/models/kev-4b.toml new file mode 100644 index 00000000000..19a67753617 --- /dev/null +++ b/providers/verathos/models/kev-4b.toml @@ -0,0 +1,15 @@ +# Price: https://api.verathos.ai/v1/models (2026-10-20). Billed on input tokens only, so output is 0. +# Serving: POST /v1/systemone; max_state_tokens 65,536, text only, as the lab entry. +schema = 2 +v2_only = true +base_model = "jaredpalmer/kev-4b" + +[api.systemone] +base_url = "https://api.verathos.ai/v1" +sdk = { aisdk = "@ai-sdk/typesafe-ai", opencodeai = "@opencode/ai/providers/typesafe-ai" } + +[cost.text.input] +price = 0.015 + +[cost.text.output] +price = 0 diff --git a/providers/verathos/provider.toml b/providers/verathos/provider.toml new file mode 100644 index 00000000000..2546d758486 --- /dev/null +++ b/providers/verathos/provider.toml @@ -0,0 +1,13 @@ +# Verathos Decide serves open-weight decision models on Bittensor subnet 96. Requests go to +# POST /v1/systemone in the System One request and answer format (state, typed questions, +# a probability per option); there is no chat completions endpoint. `api` is required by the +# schema for `@ai-sdk/openai-compatible`. Keys are `Authorization: Bearer`, created at +# https://verathos.ai/account/keys. Prices, limits and image support per model are public at +# https://api.verathos.ai/v1/models; output tokens are free. https://verathos.ai/docs/api (accessed 2026-10-20) +# opencodeai = "none": there is no chat API; each model's [api.systemone] names its SDK. +name = "Verathos" +npm = "@ai-sdk/openai-compatible" +opencodeai = "none" +api = "https://api.verathos.ai/v1" +env = ["VERATHOS_API_KEY"] +doc = "https://verathos.ai/docs/models"