Expand description
§2 module 26 model.catalog (docs/composable-harness/ COMPOSABLE-HARNESS-DESIGN.md §3.1 [capabilities.model_catalog]) — P4
of the composable-harness migration (design §5.2 phase P4: “aliases +
fallback chains (userconfig.rs:386-411) promoted into core” + the
small_model knob).
What moved here. The CLI’s alias_table/resolve_model_alias
(crates/cli/src/userconfig.rs) were CLI-only (design §1.10: “CLI model
aliases ✓ … resolve_model_alias, userconfig.rs:386-411”). This module is
the single source of truth now — DEFAULT_ALIASES is the exact same
eleven built-in aliases, byte-identical, so moving them here changes no
resolved slug for any existing caller. The CLI crate re-exports through
userconfig::alias_table/resolve_model_alias (zero call-site churn,
zero behavior change — see that module).
What’s NEW (P4). resolve_alias additionally accepts an
extra table ([capabilities.model_catalog].aliases, §3.1/§3.2:
“capabilities.model_catalog.* | CLI alias_table … + NEW
small-model/fallback”) so a user’s own config can add or override an
alias without recompiling — extra is checked BEFORE
DEFAULT_ALIASES, so a user override always wins. [resolve_fallback_chain]
resolves a [capabilities.model_catalog].fallback list of aliases/slugs
into a plain slug list the SAME way, for the D-9-adjacent “failure
fallback chain” knob (catalog §4a: “Model aliases + failure fallback
chain (resolution table before request build)”).
Scope note (S-sized, per design §5.2 P4). This module lands the
RESOLUTION TABLE only — Config::small_model/Config::model_fallback
are knobs a caller can read, not a retry/failover LOOP that automatically
re-sends a failed request against the next model in the chain. Building
that loop is a distinct, larger change (closer to §1.10’s “mid-session
model switch,” itself called out in design §5.2 as its own M-sized item,
separate from this S-sized catalog item) and is out of scope here.
Structs§
- Model
Rules - Per-model routing rules: what
[capabilities.model_catalog.models.<pattern>](and the table’s own top-level defaults) say about one model. - Resolution
- Everything
[capabilities.model_catalog]resolves into, alias-resolved: the effectivecore.model, thesmall_model(if set), and thefallbackchain (if set). Shared by both resolution paths that carry acapabilities.<name>table shaped likecrate::configfile::CapabilityConfig— the SDK’scrate::configfile::HarnessConfigresolver (materialize_config) and the CLI’s ownFileConfig-drivenbuild_config— so the alias/small-model/fallback resolution logic lives in exactly one place. - Routing
- The whole resolved routing table, carried on
crate::Config::model_routingand consulted by every routing decision.
Constants§
- DEFAULT_
ALIASES - The built-in alias → full-slug table (byte-identical to the CLI’s
original
userconfig::alias_table, moved here as the single source of truth — see the module doc). - EFFORT_
LADDER - The reasoning-effort ladder, weakest first. Spans both harnesses’ own
vocabularies: Claude Code’s
low|medium|highand Codex’snone…ultra(cc§9, cx§6/§9). A level outside the ladder is not an error — it is forwarded verbatim to the provider — but it cannot be RANKED, so an effort cap can neither clamp it nor be fooled by it (seecap_effort).
Functions§
- base_
prompt_ for - BP-5 (catalog D2 “Per-model-family base-prompt selection”, cx§2
“Per-model base instructions”: “the system prompt is selected per model
family from bundled markdown”): the base prompt
modelshould run under, orNonewhen no family pattern matches. - cap_
effort - Clamp
leveldown tocap. Returnslevelunchanged when there is no cap, when the cap does not bind, or when EITHER side is unrankable (an unknown spelling must not be silently rewritten into a ladder value the user never asked for). - effort_
rank - Position of
levelonEFFORT_LADDER, orNonefor a level this build does not rank. - pattern_
capture - Match
valueagainst a model PATTERN and return what the wildcard captured. - resolve
- Resolve
[capabilities.model_catalog]againstbase_model(typically the already-computedcore.model/ CLI--model/config value). Consulted regardless ofcapabilities.model_catalog.enabled— matching the resolver’s existing D-9 check (configfile::validate_modules), which already readsmodel_catalog.small_modelunconditionally: these are data a caller resolves against, not an activation switch. - resolve_
alias - Expand a friendly model alias to its full slug through the built-in
table alone — the no-config path, for callers that have no resolved
Routingin hand (an imported foreign session’s recorded model name, a help listing). Unknown values pass through unchanged so any real slug still works. A caller that DOES have a config resolves throughRouting::resolve_aliasinstead, which additionally honours the config’s own alias table, its patterns, and its provider/account scopes.