Roadmodel

Latest version: v0.2.9

Safety actively analyzes 945810 Python packages for vulnerabilities to keep your Python projects secure.

Scan your dependencies

Page 1 of 3

0.2.9

Added

- **Runtime availability hook.** `recommend`, `recommend_structured`, and
`build_prompt` gain an optional `unavailable_models: list[str] | None` keyword.
When supplied, the listed model ids are injected as a **runtime Step 0a
override** layered on top of the bundled `<availability-context>` defaults —
the recommender never returns them as MODEL or BACKUP. This lets an embedding
caller (the roadmodel.ai service) bench or un-bench a model from a runtime
source — e.g. a provider-availability probe — **without a package release**.
`None`/empty (the default, and every CLI/MCP call) is a no-op, so behavior is
unchanged unless a caller opts in.

0.2.8

Changed

- **The recommender no longer recommends unavailable models.** The bundled
`model-selector.txt` gains an editorial `<availability-context>` block and a
`<selection-algorithm>` **Step 0a** pre-filter (mirroring the jurisdiction
filter) that drops listed model ids from the candidate set before quality
ranking. **`claude-fable-5` (Claude Fable 5) is marked unavailable** —
Anthropic suspended access on 2026-06-12 under a US export-control directive —
so the recommender returns the next-best available model instead. The model's
catalog entry and tier ratings are retained for reference; it is excluded only
at selection time, so re-enabling is a one-line edit (276).

Added

- **Optional `BACKUP` recommendation field.** The bundled selector's
`<output-format>` now emits a `BACKUP` line (**Step 7** of the selection
algorithm) naming the next-best *available* model — preferably a different
provider/family — to fall back to when the primary is unavailable to the user.
`parse_response` captures it as an OPTIONAL field (kept out of
`_REQUIRED_KEYS`, mirroring `ORCHESTRATION`), so a provider that omits it or
emits `None` still parses with no error; `recommend_structured` surfaces it
when present (277).

Like all bundled-selector changes, both of the above reach the recommendation
LLM only via this release.

0.2.7

Changed

- The bundled `model-selector.txt` now carries the **bias-not-gate**
funding-aware `<access-selection>` prose (Phase 4.8 T2b). The recommender
builds its prompt from the package-bundled selector, so this prose only
reaches the recommendation LLM via a release — `0.2.6` still shipped the
prior hard-gating prose. The softened algorithm:
- **Step B** tags each access method funded/unfunded and **never drops**
an unfunded one (it is a valid platform that simply costs real money);
funding never changes the chosen MODEL.
- **Step C** picks the cheapest path and, when no funded method reaches
the chosen model, **still recommends that model** via its cheapest
access method and discloses the pay-per-token spend in the rationale.
- **Guardrails** prefer a funded surface only to break an exact quality
tie and never downgrade the model to avoid spend. Jurisdiction remains
the one hard filter (a compliance constraint, not a cost one).

No engine, model, cost, or API change — only the bundled selector text
(and the regenerated `model-selector.md` / `catalog.json`, whose diff is
limited to the source hash). Pairs with the service-side per-user funding
context (`user_context_text`, added in `0.2.6`) so model SELECTION honors
each user's declared funding without excluding the best model (163).

0.2.6

Added

- Optional `user_context_text: str | None` keyword on
`roadmodel.recommend.recommend` and
`roadmodel.recommend.recommend_structured`. When provided, the supplied
text is used verbatim as the user-context section of the system prompt and
the `config.user_context_path` file read is **skipped**; when `None` (the
default, and every CLI/MCP call) behavior is unchanged — the on-disk
user-context file is read exactly as before. This lets an embedding caller
(the roadmodel.ai SaaS service) inject a **per-request, per-user** funding
context — the user's held subscriptions and enabled API providers — so the
selector can prefer a model the user already funds at $0 on a quality tie,
instead of always seeing one static bundled user-context. No engine, model,
cost, or prompt-template change; purely an additive, backward-compatible
API surface.

0.2.5

Changed

- `roadmodel.recommend.build_prompt` hardens the SaaS recommender system
prompt so the recommender follows the selector spec instead of performing
the user's task:
- **Strips the bundled `model-selector.txt` `<instruction>`/`<usage>`
blocks** from the assembled system prompt. Those blocks frame the file's
IDE roadmap-*annotation* mode ("Execute the requested task in full … the
AI performs the task"), which pushed the recommender to write the user's
study plan / poem / proof inside the `RATIONALE`. The bundled file is left
untouched, so the IDE / Claude Code path keeps the full framing (187).
- **Front-loads a hardened header** restating the rules the recommender
model most often violates against the deep spec: quality-over-cost (no
cost-demotion below the top reachable tier, 185), the funded-platform
preference order (186), `THINKING: N/A` on surfaces that expose no
thinking dial (188), and strict PRIMARY-category classification (189).
- **Wraps the user prompt** in `<task-to-classify>` so the model reads it
as delimited input rather than an instruction to execute.

No engine, model, or cost change — the free-tier recommender still runs the
same provider; only the prompt text changes. Validated against Gemini 2.5
Flash (prod params, repeated runs): task-execution leak eliminated,
quality-undershoots corrected to the top reachable tier, platform routing
moved to the $0-funded surfaces, and run-to-run pick determinism improved.

0.2.4

Added

- Optional `temperature: float | None` keyword on
`roadmodel.recommend.recommend` and
`roadmodel.recommend.recommend_structured`, plumbed through the
`ProviderAdapter` Protocol (mirrors the `0.2.3` `thinking_budget`
work). When set, `providers.google` forwards it to the Gemini SDK as
`config.temperature`; the guard uses `is not None`, so `temperature=0.0`
(greedy/deterministic) is honored rather than dropped.
`providers.anthropic` and `providers.openai` accept the keyword for
Protocol parity but do not forward it. When unset, every provider keeps
its prior behavior exactly, so this is a no-op until a caller opts in.

Motivation: the free-tier recommender ran Gemini at its default sampling
temperature (~1.0), so the same `task_description` returned different
model picks run-to-run (a production dogfooding sweep saw ~25% of
identical requests flip to a different model). Callers can now pin a low
or zero temperature for consistent recommendations (176).

- `roadmodel.cost.canonical_model_name` and
`roadmodel.cost.canonical_platform_name`: resolve a model or
access-method **id-or-name** to its catalog display name, returning the
input unchanged on any catalog miss (never raise) (174).

Changed

- `recommend_structured` now canonicalizes the recommended model and
platform to their catalog display names before building the payload (and
reuses them for the cost estimate + comparison-table calls). The selector
LLM emits either the catalog id/slug or the display name freely, which
made the response header (raw) disagree with the cost/comparison table
(catalog-canonical) within one response and risked silently dropping the
cost panel on an unrecognized label. Falls back to the raw value on a
catalog miss (174).

Page 1 of 3

© 2026 Safety CLI Cybersecurity Inc. All Rights Reserved.