From 7eab4a732c64d17066a8338785c3014637572469 Mon Sep 17 00:00:00 2001 From: TheCheetah Date: Sat, 1 Aug 2026 23:59:46 +0100 Subject: [PATCH 1/3] fix: add DeepSeek V4 Flash to picker catalog --- docs/03-one-endpoint-gpt-claude-gemini-deepseek.md | 3 ++- src/clawrouter_hermes/models.py | 1 + src/clawrouter_hermes/provider_template/init.py.tmpl | 1 + src/clawrouter_hermes/skills/clawrouter/SKILL.md | 2 +- tests/test_provider_template.py | 1 + 5 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/03-one-endpoint-gpt-claude-gemini-deepseek.md b/docs/03-one-endpoint-gpt-claude-gemini-deepseek.md index 83ea8a2..81bb7a9 100644 --- a/docs/03-one-endpoint-gpt-claude-gemini-deepseek.md +++ b/docs/03-one-endpoint-gpt-claude-gemini-deepseek.md @@ -76,7 +76,8 @@ blockrun/xai/grok-4.5 blockrun/minimax/minimax-m3 blockrun/moonshot/kimi-k3 blockrun/deepseek/deepseek-v4-pro -…46 curated entries (66 models via the gateway) +blockrun/deepseek/deepseek-v4-flash +…47 curated entries (67 models via the gateway) ``` Set the model to `blockrun/auto` and the gateway's router picks a model per request diff --git a/src/clawrouter_hermes/models.py b/src/clawrouter_hermes/models.py index 15c6a28..71300af 100644 --- a/src/clawrouter_hermes/models.py +++ b/src/clawrouter_hermes/models.py @@ -46,6 +46,7 @@ "blockrun/moonshot/kimi-k3", "blockrun/qwen/qwen3.7-max", "blockrun/deepseek/deepseek-v4-pro", + "blockrun/deepseek/deepseek-v4-flash", "blockrun/deepseek/deepseek-chat", "blockrun/deepseek/deepseek-reasoner", "blockrun/free/mistral-large-3-675b", diff --git a/src/clawrouter_hermes/provider_template/init.py.tmpl b/src/clawrouter_hermes/provider_template/init.py.tmpl index 9bb24e3..2923959 100644 --- a/src/clawrouter_hermes/provider_template/init.py.tmpl +++ b/src/clawrouter_hermes/provider_template/init.py.tmpl @@ -81,6 +81,7 @@ _STATIC_FALLBACKS = ( "blockrun/moonshot/kimi-k3", "blockrun/qwen/qwen3.7-max", "blockrun/deepseek/deepseek-v4-pro", + "blockrun/deepseek/deepseek-v4-flash", "blockrun/deepseek/deepseek-chat", "blockrun/deepseek/deepseek-reasoner", "blockrun/free/mistral-large-3-675b", diff --git a/src/clawrouter_hermes/skills/clawrouter/SKILL.md b/src/clawrouter_hermes/skills/clawrouter/SKILL.md index 10ded6d..9909752 100644 --- a/src/clawrouter_hermes/skills/clawrouter/SKILL.md +++ b/src/clawrouter_hermes/skills/clawrouter/SKILL.md @@ -164,7 +164,7 @@ Rules handle ~80% of requests in <1ms. Only ambiguous queries hit the LLM classi ## Available Models -66 models including: claude-fable-5, claude-opus-5, claude-opus-4.8, claude-opus-4.7, claude-sonnet-5, claude-sonnet-4.6, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gemini-3.1-pro, gemini-3.5-flash, grok-4.5, grok-4.3, grok-build-0.1, deepseek-v4-pro, deepseek-chat, glm-5.2, kimi-k3, minimax-m3, qwen3.7-max, and the curated free models (mistral-large-3-675b, qwen3-next-80b-a3b-instruct, seed-oss-36b, nemotron-3-nano-omni-30b-a3b-reasoning [vision], mistral-nemotron, step-3.7-flash, nemotron-nano-9b-v2, nemotron-nano-12b-v2-vl [vision]). +67 models including: claude-fable-5, claude-opus-5, claude-opus-4.8, claude-opus-4.7, claude-sonnet-5, claude-sonnet-4.6, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gemini-3.1-pro, gemini-3.5-flash, grok-4.5, grok-4.3, grok-build-0.1, deepseek-v4-pro, deepseek-v4-flash, deepseek-chat, glm-5.2, kimi-k3, minimax-m3, qwen3.7-max, and the curated free models (mistral-large-3-675b, qwen3-next-80b-a3b-instruct, seed-oss-36b, nemotron-3-nano-omni-30b-a3b-reasoning [vision], mistral-nemotron, step-3.7-flash, nemotron-nano-9b-v2, nemotron-nano-12b-v2-vl [vision]). ## Built-in Agent Tools diff --git a/tests/test_provider_template.py b/tests/test_provider_template.py index 40dd416..581970d 100644 --- a/tests/test_provider_template.py +++ b/tests/test_provider_template.py @@ -31,6 +31,7 @@ "blockrun/moonshot/kimi-k3", "blockrun/qwen/qwen3.7-max", "blockrun/deepseek/deepseek-v4-pro", + "blockrun/deepseek/deepseek-v4-flash", "blockrun/free/mistral-large-3-675b", ) From d30b17beb183f193d7ab30f58c9ec33268cf7edb Mon Sep 17 00:00:00 2001 From: TheCheetah Date: Sun, 2 Aug 2026 00:01:13 +0100 Subject: [PATCH 2/3] fix: keep gateway model count synced --- docs/03-one-endpoint-gpt-claude-gemini-deepseek.md | 2 +- src/clawrouter_hermes/skills/clawrouter/SKILL.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/03-one-endpoint-gpt-claude-gemini-deepseek.md b/docs/03-one-endpoint-gpt-claude-gemini-deepseek.md index 81bb7a9..daf16f1 100644 --- a/docs/03-one-endpoint-gpt-claude-gemini-deepseek.md +++ b/docs/03-one-endpoint-gpt-claude-gemini-deepseek.md @@ -77,7 +77,7 @@ blockrun/minimax/minimax-m3 blockrun/moonshot/kimi-k3 blockrun/deepseek/deepseek-v4-pro blockrun/deepseek/deepseek-v4-flash -…47 curated entries (67 models via the gateway) +…47 curated entries (66 models via the gateway) ``` Set the model to `blockrun/auto` and the gateway's router picks a model per request diff --git a/src/clawrouter_hermes/skills/clawrouter/SKILL.md b/src/clawrouter_hermes/skills/clawrouter/SKILL.md index 9909752..eb76425 100644 --- a/src/clawrouter_hermes/skills/clawrouter/SKILL.md +++ b/src/clawrouter_hermes/skills/clawrouter/SKILL.md @@ -164,7 +164,7 @@ Rules handle ~80% of requests in <1ms. Only ambiguous queries hit the LLM classi ## Available Models -67 models including: claude-fable-5, claude-opus-5, claude-opus-4.8, claude-opus-4.7, claude-sonnet-5, claude-sonnet-4.6, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gemini-3.1-pro, gemini-3.5-flash, grok-4.5, grok-4.3, grok-build-0.1, deepseek-v4-pro, deepseek-v4-flash, deepseek-chat, glm-5.2, kimi-k3, minimax-m3, qwen3.7-max, and the curated free models (mistral-large-3-675b, qwen3-next-80b-a3b-instruct, seed-oss-36b, nemotron-3-nano-omni-30b-a3b-reasoning [vision], mistral-nemotron, step-3.7-flash, nemotron-nano-9b-v2, nemotron-nano-12b-v2-vl [vision]). +66 models including: claude-fable-5, claude-opus-5, claude-opus-4.8, claude-opus-4.7, claude-sonnet-5, claude-sonnet-4.6, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gemini-3.1-pro, gemini-3.5-flash, grok-4.5, grok-4.3, grok-build-0.1, deepseek-v4-pro, deepseek-v4-flash, deepseek-chat, glm-5.2, kimi-k3, minimax-m3, qwen3.7-max, and the curated free models (mistral-large-3-675b, qwen3-next-80b-a3b-instruct, seed-oss-36b, nemotron-3-nano-omni-30b-a3b-reasoning [vision], mistral-nemotron, step-3.7-flash, nemotron-nano-9b-v2, nemotron-nano-12b-v2-vl [vision]). ## Built-in Agent Tools From 237341745c21e0f82968fb39f1f45482a8fd9971 Mon Sep 17 00:00:00 2001 From: 1bcMax Date: Sun, 2 Aug 2026 12:55:47 -0500 Subject: [PATCH 3/3] fix: use the free deepseek-v4-flash catalog entry, not the retired paid alias blockrun/deepseek/deepseek-v4-flash was never a real SKU: the gateway removed paid V4 Flash and kept only a legacy alias to deepseek-chat, so the picker entry duplicated deepseek-chat under a delisted name (and the bare string deepseek-v4-flash routes to the FREE model in ClawRouter, so one label billed two prices). The genuinely missing curated entry is free/deepseek-v4-flash, which top-models.json lists after free/mistral-large-3-675b. - move the entry to the free tail across models.py, the provider template, tests, SKILL.md, and docs - append free/qwen3-next-80b-a3b-instruct to the end of the free tail (post-top-models addition; was interleaved, contradicting the mirror-then-append convention the test documents) - deny-list blockrun/deepseek/deepseek-v4-flash in retired_models so a bad merge can't resurrect it - add a cross-catalog mirror test against a sibling ClawRouter checkout (skips in CI) validating membership and relative order against top-models.json --- ...one-endpoint-gpt-claude-gemini-deepseek.md | 2 +- src/clawrouter_hermes/models.py | 4 +- .../provider_template/init.py.tmpl | 4 +- .../skills/clawrouter/SKILL.md | 2 +- tests/test_provider_template.py | 49 ++++++++++++++++++- 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/docs/03-one-endpoint-gpt-claude-gemini-deepseek.md b/docs/03-one-endpoint-gpt-claude-gemini-deepseek.md index daf16f1..3132fd7 100644 --- a/docs/03-one-endpoint-gpt-claude-gemini-deepseek.md +++ b/docs/03-one-endpoint-gpt-claude-gemini-deepseek.md @@ -76,7 +76,7 @@ blockrun/xai/grok-4.5 blockrun/minimax/minimax-m3 blockrun/moonshot/kimi-k3 blockrun/deepseek/deepseek-v4-pro -blockrun/deepseek/deepseek-v4-flash +blockrun/free/deepseek-v4-flash …47 curated entries (66 models via the gateway) ``` diff --git a/src/clawrouter_hermes/models.py b/src/clawrouter_hermes/models.py index 71300af..eb64214 100644 --- a/src/clawrouter_hermes/models.py +++ b/src/clawrouter_hermes/models.py @@ -46,17 +46,17 @@ "blockrun/moonshot/kimi-k3", "blockrun/qwen/qwen3.7-max", "blockrun/deepseek/deepseek-v4-pro", - "blockrun/deepseek/deepseek-v4-flash", "blockrun/deepseek/deepseek-chat", "blockrun/deepseek/deepseek-reasoner", "blockrun/free/mistral-large-3-675b", - "blockrun/free/qwen3-next-80b-a3b-instruct", + "blockrun/free/deepseek-v4-flash", "blockrun/free/seed-oss-36b", "blockrun/free/nemotron-3-nano-omni-30b-a3b-reasoning", "blockrun/free/mistral-nemotron", "blockrun/free/step-3.7-flash", "blockrun/free/nemotron-nano-9b-v2", "blockrun/free/nemotron-nano-12b-v2-vl", + "blockrun/free/qwen3-next-80b-a3b-instruct", ) def chat_models() -> list[str]: diff --git a/src/clawrouter_hermes/provider_template/init.py.tmpl b/src/clawrouter_hermes/provider_template/init.py.tmpl index 2923959..381b36b 100644 --- a/src/clawrouter_hermes/provider_template/init.py.tmpl +++ b/src/clawrouter_hermes/provider_template/init.py.tmpl @@ -81,17 +81,17 @@ _STATIC_FALLBACKS = ( "blockrun/moonshot/kimi-k3", "blockrun/qwen/qwen3.7-max", "blockrun/deepseek/deepseek-v4-pro", - "blockrun/deepseek/deepseek-v4-flash", "blockrun/deepseek/deepseek-chat", "blockrun/deepseek/deepseek-reasoner", "blockrun/free/mistral-large-3-675b", - "blockrun/free/qwen3-next-80b-a3b-instruct", + "blockrun/free/deepseek-v4-flash", "blockrun/free/seed-oss-36b", "blockrun/free/nemotron-3-nano-omni-30b-a3b-reasoning", "blockrun/free/mistral-nemotron", "blockrun/free/step-3.7-flash", "blockrun/free/nemotron-nano-9b-v2", "blockrun/free/nemotron-nano-12b-v2-vl", + "blockrun/free/qwen3-next-80b-a3b-instruct", ) diff --git a/src/clawrouter_hermes/skills/clawrouter/SKILL.md b/src/clawrouter_hermes/skills/clawrouter/SKILL.md index eb76425..fbd1fec 100644 --- a/src/clawrouter_hermes/skills/clawrouter/SKILL.md +++ b/src/clawrouter_hermes/skills/clawrouter/SKILL.md @@ -164,7 +164,7 @@ Rules handle ~80% of requests in <1ms. Only ambiguous queries hit the LLM classi ## Available Models -66 models including: claude-fable-5, claude-opus-5, claude-opus-4.8, claude-opus-4.7, claude-sonnet-5, claude-sonnet-4.6, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gemini-3.1-pro, gemini-3.5-flash, grok-4.5, grok-4.3, grok-build-0.1, deepseek-v4-pro, deepseek-v4-flash, deepseek-chat, glm-5.2, kimi-k3, minimax-m3, qwen3.7-max, and the curated free models (mistral-large-3-675b, qwen3-next-80b-a3b-instruct, seed-oss-36b, nemotron-3-nano-omni-30b-a3b-reasoning [vision], mistral-nemotron, step-3.7-flash, nemotron-nano-9b-v2, nemotron-nano-12b-v2-vl [vision]). +66 models including: claude-fable-5, claude-opus-5, claude-opus-4.8, claude-opus-4.7, claude-sonnet-5, claude-sonnet-4.6, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gemini-3.1-pro, gemini-3.5-flash, grok-4.5, grok-4.3, grok-build-0.1, deepseek-v4-pro, deepseek-chat, glm-5.2, kimi-k3, minimax-m3, qwen3.7-max, and the curated free models (mistral-large-3-675b, deepseek-v4-flash, seed-oss-36b, nemotron-3-nano-omni-30b-a3b-reasoning [vision], mistral-nemotron, step-3.7-flash, nemotron-nano-9b-v2, nemotron-nano-12b-v2-vl [vision], qwen3-next-80b-a3b-instruct). ## Built-in Agent Tools diff --git a/tests/test_provider_template.py b/tests/test_provider_template.py index 581970d..33726d1 100644 --- a/tests/test_provider_template.py +++ b/tests/test_provider_template.py @@ -4,6 +4,7 @@ import ast import importlib.resources as resources +import json import sys import types from pathlib import Path @@ -31,8 +32,8 @@ "blockrun/moonshot/kimi-k3", "blockrun/qwen/qwen3.7-max", "blockrun/deepseek/deepseek-v4-pro", - "blockrun/deepseek/deepseek-v4-flash", "blockrun/free/mistral-large-3-675b", + "blockrun/free/deepseek-v4-flash", ) @@ -151,18 +152,23 @@ def test_curated_picker_catalog_orders_featured_models(): assert chat_models[-len(free_tail):] == free_tail assert free_tail == [ "blockrun/free/mistral-large-3-675b", - "blockrun/free/qwen3-next-80b-a3b-instruct", + "blockrun/free/deepseek-v4-flash", "blockrun/free/seed-oss-36b", "blockrun/free/nemotron-3-nano-omni-30b-a3b-reasoning", "blockrun/free/mistral-nemotron", "blockrun/free/step-3.7-flash", "blockrun/free/nemotron-nano-9b-v2", "blockrun/free/nemotron-nano-12b-v2-vl", + "blockrun/free/qwen3-next-80b-a3b-instruct", ] # Retired models must not reappear in the picker. Append here on every # catalog retirement so a bad merge can't resurrect them. retired_models = frozenset({ "blockrun/free/qwen3-coder-480b", # NVIDIA EOL 2026-06-14 + # Never a real SKU: the gateway removed paid V4 Flash and kept only a + # legacy alias to deepseek/deepseek-chat, so this ID smoke-tests green + # while duplicating deepseek-chat. The free model is free/deepseek-v4-flash. + "blockrun/deepseek/deepseek-v4-flash", # Dropped from the live BlockRun catalog by 2026-07-17: "blockrun/xai/grok-4-1-fast-reasoning", "blockrun/xai/grok-4-0709", @@ -175,6 +181,45 @@ def test_curated_picker_catalog_orders_featured_models(): assert not set(chat_models) & retired_models +#: Curated entries that postdate the ClawRouter top-models.json snapshot. +#: They are appended after the mirrored free tail rather than interleaved. +POST_TOP_MODELS_ADDITIONS = frozenset({ + "blockrun/free/qwen3-next-80b-a3b-instruct", +}) + + +def test_curated_picker_catalog_mirrors_clawrouter_top_models(): + """Membership + relative order must match ClawRouter's top-models.json. + + The gateway's MODEL_ALIASES table makes phantom IDs smoke-test green: + blockrun/deepseek/deepseek-v4-flash returned HTTP 200 via a legacy alias + to deepseek-chat while never being a real SKU (PR #27). Catalog membership + therefore has to be validated against top-models.json, not the wire. + Runs only where a sibling ClawRouter checkout exists; CI skips. + """ + top_models_path = ( + _repo_root().parent / "ClawRouter" / "src" / "top-models.json" + ) + if not top_models_path.is_file(): + pytest.skip("sibling ClawRouter checkout not available") + top_models = json.loads(top_models_path.read_text(encoding="utf-8")) + + from clawrouter_hermes import models + + mirrored = [ + model.removeprefix("blockrun/") + for model in models.chat_models() + if model not in POST_TOP_MODELS_ADDITIONS + ] + unknown = [model for model in mirrored if model not in top_models] + assert not unknown, f"curated IDs missing from top-models.json: {unknown}" + positions = {model: idx for idx, model in enumerate(top_models)} + order = [positions[model] for model in mirrored] + assert order == sorted(order), ( + "curated order diverges from top-models.json" + ) + + def test_patch_hermes_model_catalog_uses_curated_clawrouter_only(monkeypatch): import clawrouter_hermes.cli as cli_module from clawrouter_hermes import models