Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/03-one-endpoint-gpt-claude-gemini-deepseek.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 (<!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models via the gateway)
blockrun/free/deepseek-v4-flash
…47 curated entries (<!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models via the gateway)
```

Set the model to `blockrun/auto` and the gateway's router picks a model per request
Expand Down
3 changes: 2 additions & 1 deletion src/clawrouter_hermes/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,14 @@
"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]:
Expand Down
3 changes: 2 additions & 1 deletion src/clawrouter_hermes/provider_template/init.py.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,14 @@ _STATIC_FALLBACKS = (
"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",
)


Expand Down
2 changes: 1 addition & 1 deletion src/clawrouter_hermes/skills/clawrouter/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ Rules handle ~80% of requests in <1ms. Only ambiguous queries hit the LLM classi

## Available Models

<!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> 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]).
<!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> 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

Expand Down
48 changes: 47 additions & 1 deletion tests/test_provider_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import ast
import importlib.resources as resources
import json
import sys
import types
from pathlib import Path
Expand Down Expand Up @@ -32,6 +33,7 @@
"blockrun/qwen/qwen3.7-max",
"blockrun/deepseek/deepseek-v4-pro",
"blockrun/free/mistral-large-3-675b",
"blockrun/free/deepseek-v4-flash",
)


Expand Down Expand Up @@ -150,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",
Expand All @@ -174,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
Expand Down
Loading