roadmodel 0.2.76__tar.gz → 0.2.77__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {roadmodel-0.2.76 → roadmodel-0.2.77}/PKG-INFO +1 -1
- {roadmodel-0.2.76 → roadmodel-0.2.77}/pyproject.toml +1 -1
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/__init__.py +1 -1
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/cost.py +5 -2
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/recommend.py +24 -1
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/scoring.py +1 -1
- {roadmodel-0.2.76 → roadmodel-0.2.77}/.gitignore +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/LICENSE +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/NOTICE +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/README.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/docs/benchmarks.json +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/docs/catalog.json +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/docs/context-windows.json +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/docs/model-selector.txt +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/docs/model-tier-cost-scale.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/docs/settings-display.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/docs/templates/phase-roadmap-template.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/docs/templates/planning-kit-how-to-use.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/docs/templates/project-roadmap-template.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/docs/templates/prompt-phase-roadmap.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/docs/templates/prompt-project-roadmap.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/docs/user-context.example.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/hatch_build.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/infra/README.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/infra/gcp-killswitch/README.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/infra/supabase/README.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/roadmodel/data/benchmarks.json +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/roadmodel/data/catalog.json +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/roadmodel/data/context-windows.json +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/roadmodel/data/model-selector.txt +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/roadmodel/data/model-tier-cost-scale.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/roadmodel/data/phase-roadmap-template.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/roadmodel/data/planning-kit-how-to-use.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/roadmodel/data/project-roadmap-template.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/roadmodel/data/prompt-phase-roadmap.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/roadmodel/data/prompt-project-roadmap.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/roadmodel/data/settings-display.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/roadmodel/data/user-context.example.md +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/scripts/agent_context.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/scripts/agent_rules.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/scripts/update_projects.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/scripts/updater_lock.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/scripts/upgrade_fleet.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/scripts/worktree_memory.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/__main__.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/cli.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/config.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/errors.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/mcp_server.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/providers/__init__.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/providers/anthropic.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/providers/google.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/providers/openai.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/providers/openai_compatible.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/providers/registry.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/usage.py +0 -0
- {roadmodel-0.2.76 → roadmodel-0.2.77}/src/roadmodel/user_context.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: roadmodel
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.77
|
|
4
4
|
Summary: BYO-key CLI that recommends the right AI model, platform, and settings for a prompt.
|
|
5
5
|
Project-URL: Homepage, https://roadmodel.ai
|
|
6
6
|
Project-URL: Repository, https://github.com/nathanramoscfa/roadmodel
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# src/roadmodel/__init__.py
|
|
2
|
-
__version__ = "0.2.
|
|
2
|
+
__version__ = "0.2.77"
|
|
@@ -404,7 +404,7 @@ _HOST_METHODS: frozenset[str] = frozenset({"antigravity"})
|
|
|
404
404
|
_LOCAL_PROVIDERS: frozenset[str] = frozenset({"ollama"})
|
|
405
405
|
|
|
406
406
|
|
|
407
|
-
def model_provider(model_ref: str) -> str | None:
|
|
407
|
+
def model_provider(model_ref: str, catalog: dict[str, Any] | None = None) -> str | None:
|
|
408
408
|
"""Resolve a model id-or-name to its MAKER (the company that produces it):
|
|
409
409
|
``anthropic`` / ``openai`` / ``google`` / ``xai`` / ``deepseek`` / ``mistral``
|
|
410
410
|
/ ``zai`` / ``groq`` / ``cursor`` …
|
|
@@ -419,7 +419,10 @@ def model_provider(model_ref: str) -> str | None:
|
|
|
419
419
|
rather than dropping a valid backup.
|
|
420
420
|
"""
|
|
421
421
|
try:
|
|
422
|
-
catalog
|
|
422
|
+
# A caller that already holds the catalog passes it: the scorer asks
|
|
423
|
+
# once per candidate, and re-parsing the JSON each time was most of a
|
|
424
|
+
# ladder table's cost (Phase 4.5, 2026-10-08).
|
|
425
|
+
catalog = catalog if catalog is not None else _load_catalog()
|
|
423
426
|
model_id = str(_resolve_model(model_ref, catalog)["id"])
|
|
424
427
|
except (ValueError, BundledDocNotFoundError, KeyError, TypeError):
|
|
425
428
|
return None
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
|
|
4
4
|
import contextvars
|
|
5
5
|
import json
|
|
6
|
+
import os
|
|
6
7
|
import re
|
|
7
8
|
from collections import Counter
|
|
8
9
|
from concurrent.futures import ThreadPoolExecutor
|
|
@@ -1553,15 +1554,37 @@ def _enforce_table_effort(ladder: dict[str, dict[str, str]], row: scoring.Ladder
|
|
|
1553
1554
|
return adjusted
|
|
1554
1555
|
|
|
1555
1556
|
|
|
1557
|
+
# Ladder tables already computed in this process, by user-context text, the
|
|
1558
|
+
# unavailable models and any catalog override. The catalog and benchmarks are
|
|
1559
|
+
# bundled, so one context always yields the same table; rebuilding it (28 rows,
|
|
1560
|
+
# each ranking the whole pool) cost the hosted service about a second a request
|
|
1561
|
+
# for a well-funded user (Phase 4.5 soak, 2026-10-08: B9 latency). Rows are
|
|
1562
|
+
# read, never mutated. Oldest entry out first past _TABLE_CACHE_MAX.
|
|
1563
|
+
_TABLE_CACHE: dict[tuple[str, tuple[str, ...], str], dict[str, scoring.Ladder]] = {}
|
|
1564
|
+
_TABLE_CACHE_MAX: Final = 64
|
|
1565
|
+
|
|
1566
|
+
|
|
1556
1567
|
def _ladder_table_for(
|
|
1557
1568
|
user_context_text: str, unavailable_models: list[str] | None
|
|
1558
1569
|
) -> dict[str, scoring.Ladder]:
|
|
1559
1570
|
"""The scorer's ladder table for this user-context, or an empty one if it
|
|
1560
1571
|
cannot be computed: a scoring failure costs the table, never the call."""
|
|
1572
|
+
key = (
|
|
1573
|
+
user_context_text,
|
|
1574
|
+
tuple(sorted(unavailable_models or [])),
|
|
1575
|
+
os.environ.get("ROADMODEL_CATALOG_PATH", ""),
|
|
1576
|
+
)
|
|
1577
|
+
cached = _TABLE_CACHE.get(key)
|
|
1578
|
+
if cached is not None:
|
|
1579
|
+
return cached
|
|
1561
1580
|
try:
|
|
1562
|
-
|
|
1581
|
+
table = scoring.ladder_table(user_context_text, unavailable_models=unavailable_models)
|
|
1563
1582
|
except Exception: # noqa: BLE001 - fail open to the free-choice ladder
|
|
1564
1583
|
return {}
|
|
1584
|
+
if len(_TABLE_CACHE) >= _TABLE_CACHE_MAX:
|
|
1585
|
+
_TABLE_CACHE.pop(next(iter(_TABLE_CACHE)), None)
|
|
1586
|
+
_TABLE_CACHE[key] = table
|
|
1587
|
+
return table
|
|
1565
1588
|
|
|
1566
1589
|
|
|
1567
1590
|
def _fit_row_to_input(
|
|
@@ -1034,7 +1034,7 @@ def rank(
|
|
|
1034
1034
|
if str(model.get("jurisdiction", "")).lower() not in juris:
|
|
1035
1035
|
excluded.append({"model": model_id, "reason": "jurisdiction"})
|
|
1036
1036
|
continue
|
|
1037
|
-
provider = _cost.model_provider(model_id) or str(model.get("provider", "unknown"))
|
|
1037
|
+
provider = _cost.model_provider(model_id, cat) or str(model.get("provider", "unknown"))
|
|
1038
1038
|
quality, source, letter = _quality(model, task, bench, scale)
|
|
1039
1039
|
points = _evidence_points(model_id, task, bench, scale)
|
|
1040
1040
|
shortfall = max(0.0, requirement - quality)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|