Skip to content

Commit 56e98be

Browse files
committed
Enforce distinct routing quality tiers
1 parent 2d6e138 commit 56e98be

17 files changed

Lines changed: 409 additions & 212 deletions

openclaw-plugin/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@anjieyang/uncommon-route",
3-
"version": "0.7.20",
3+
"version": "0.7.21",
44
"description": "OpenClaw plugin for UncommonRoute, the local LLM router that cuts premium-model spend",
55
"type": "module",
66
"main": "src/index.js",

openclaw-plugin/src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import { spawn, execSync } from "node:child_process";
1717
import { setTimeout as sleep } from "node:timers/promises";
1818

19-
const VERSION = "0.7.20";
19+
const VERSION = "0.7.21";
2020
const DEFAULT_PORT = 8403;
2121
const DEFAULT_UPSTREAM = "";
2222
const HEALTH_TIMEOUT_MS = 15_000;

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "uncommon-route"
3-
version = "0.7.20"
3+
version = "0.7.21"
44
description = "Local LLM router that cuts premium-model spend with adaptive 3-tier routing, OpenAI + Anthropic compatible"
55
requires-python = ">=3.11"
66
license = "MIT"

tests/test_model_experience.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,12 +262,12 @@ def test_route_adapts_to_model_experience() -> None:
262262
store = ModelExperienceStore(storage=InMemoryModelExperienceStorage())
263263
for _ in range(6):
264264
store.observe(
265-
"moonshot/kimi-k2.5",
265+
"nvidia/gpt-oss-120b",
266266
RoutingMode.AUTO,
267267
Tier.SIMPLE,
268268
success=False,
269269
)
270-
store.record_feedback("moonshot/kimi-k2.5", RoutingMode.AUTO, Tier.SIMPLE, "weak")
270+
store.record_feedback("nvidia/gpt-oss-120b", RoutingMode.AUTO, Tier.SIMPLE, "weak")
271271
store.observe(
272272
"google/gemini-2.5-flash-lite",
273273
RoutingMode.AUTO,
@@ -283,10 +283,10 @@ def test_route_adapts_to_model_experience() -> None:
283283
for _ in range(10):
284284
decision = route("hello", model_experience=store)
285285
gemini_score = next((s for s in decision.candidate_scores if s.model == "google/gemini-2.5-flash-lite"), None)
286-
kimi_score = next((s for s in decision.candidate_scores if s.model == "moonshot/kimi-k2.5"), None)
287-
if gemini_score and kimi_score and gemini_score.predicted_quality > kimi_score.predicted_quality:
286+
gpt_oss_score = next((s for s in decision.candidate_scores if s.model == "nvidia/gpt-oss-120b"), None)
287+
if gemini_score and gpt_oss_score and gemini_score.predicted_quality > gpt_oss_score.predicted_quality:
288288
gemini_wins += 1
289-
assert gemini_wins >= 5, f"Gemini (positive experience) should beat kimi (negative) majority of the time, got {gemini_wins}/10"
289+
assert gemini_wins >= 5, f"Gemini (positive experience) should beat gpt-oss (negative) majority of the time, got {gemini_wins}/10"
290290
finally:
291291
selector._rng.setstate(rng_state)
292292

tests/test_providers.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
remove_provider,
1515
select_preferred_model,
1616
)
17+
from uncommon_route.router.types import RoutingFeatures, Tier
1718

1819

1920
@pytest.fixture(autouse=True)
@@ -145,7 +146,11 @@ def test_route_without_byok_uses_default(self) -> None:
145146
def test_route_byok_reasoning_tier(self) -> None:
146147
from uncommon_route import route
147148
keyed = {"deepseek/deepseek-reasoner"}
148-
decision = route("prove that sqrt(2) is irrational", user_keyed_models=keyed)
149+
decision = route(
150+
"prove that sqrt(2) is irrational",
151+
routing_features=RoutingFeatures(prefers_reasoning=True, tier_floor=Tier.COMPLEX),
152+
user_keyed_models=keyed,
153+
)
149154
assert decision.model == "deepseek/deepseek-reasoner"
150155
assert "byok-preferred" in decision.method
151156

tests/test_proxy.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,65 @@ def test_selector_preview_caps_tool_selection_to_medium(self, client: TestClient
785785
assert data["step_type"] == "tool-selection"
786786
assert data["served_tier"] == "MEDIUM"
787787

788+
def test_selector_preview_caps_claude_code_title_sidechannel_to_simple(self, client: TestClient) -> None:
789+
resp = client.post("/v1/selector", json={
790+
"model": "uncommon-route/auto",
791+
"messages": [
792+
{
793+
"role": "system",
794+
"content": (
795+
"You are Claude Code. Generate a concise, sentence-case title "
796+
'for this coding session. Return JSON with a single "title" field.'
797+
),
798+
},
799+
{"role": "user", "content": "帮我创建一个新的 Python 项目目录,叫 weather-cli"},
800+
],
801+
"stream": True,
802+
})
803+
804+
assert resp.status_code == 200
805+
data = resp.json()
806+
assert data["served_tier"] == "SIMPLE"
807+
assert data["served_quality"] == "economy"
808+
assert "tier-cap-preserved(title-generation)" in data["reasoning"]
809+
810+
def test_selector_preview_ignores_wrapper_context_for_followup_floor(self, client: TestClient) -> None:
811+
resp = client.post("/v1/selector", json={
812+
"model": "uncommon-route/auto",
813+
"messages": [
814+
{
815+
"role": "user",
816+
"content": [
817+
{
818+
"type": "text",
819+
"text": (
820+
"<system-reminder>\n"
821+
"Design a distributed platform with CRDTs, websocket fanout, "
822+
"permission boundaries, audit logging, and rollout plans.\n"
823+
"</system-reminder>"
824+
),
825+
},
826+
{"type": "text", "text": "hello"},
827+
],
828+
},
829+
{"role": "assistant", "content": "Hi."},
830+
{"role": "user", "content": "帮我创建一个新的 Python 项目目录,叫 weather-cli"},
831+
],
832+
"tools": [{
833+
"type": "function",
834+
"function": {
835+
"name": "bash",
836+
"description": "Run shell commands",
837+
"parameters": {"type": "object", "properties": {}},
838+
},
839+
}],
840+
})
841+
842+
assert resp.status_code == 200
843+
data = resp.json()
844+
assert "context-followup-floor=COMPLEX" not in data["reasoning"]
845+
assert data["served_tier"] in {"SIMPLE", "MEDIUM"}
846+
788847
def test_route_preview_uses_live_selector_router(self, client: TestClient) -> None:
789848
resp = client.post("/v1/route-preview", json={
790849
"prompt": "Create a Python CLI that fetches weather and add tests.",

0 commit comments

Comments
 (0)