///|
/// `/model pick` support.
///
/// When the `/model` slot argument is not a real slot but the effort keyword
/// `pick`, the slot argument names a provider: the command reads that
/// provider's registered `ModelMetricsSource`, scores the eligible
/// slot/effort pairs on the four scored dimensions (IQ, token efficiency,
/// cost, duration) under the priority gradient 分数(IQ) > tokens 效率比 >
/// 金钱 > 时间, and auto-switches to the winner. Metrics are vendor-stated
/// facts; every failure raises instead of estimating.
///|
/// Reserved `/model` effort keyword that turns a provider id into a pick
/// command; only consulted when the id is not a real slot.
let pick_keyword : String = "pick"
///|
/// Score points charged per 1M amortized tokens per solved problem (unit:
/// points per million tokens; the tokens 效率比 dimension). The three
/// penalty weights below encode the priority gradient 分数(IQ) > tokens >
/// 金钱 > 时间: over the live GPT pool the per-dimension contribution spread
/// orders tokens (~25 points) above money (~15 points) above time (~1.4
/// points), all below the meaningful IQ spread's decisiveness.
///
/// Worked calibration (2026-09-10 live anchor gpt-6-astra:medium: 107.81 IQ
/// @ $2.26, 9.0 minutes, 1.53M amortized tokens per solved problem):
/// `107.81 - 1.0 * 1.53 - 2.0 * 2.26 - 0.5 * 0.9 = 101.31`, the winner.
/// gpt-5.6-luna:max (102.23 IQ but 26.34M amortized tokens per solved
/// problem) falls to 72.96: its 26-point token penalty dwarfs the ~3.4
/// points its cheaper price saves.
let pick_token_penalty_per_m : Double = 1.0
///|
/// Score points charged per US dollar of average run cost (unit: points per
/// dollar; the 金钱 dimension, below tokens in the gradient).
let pick_cost_penalty_per_usd : Double = 2.0
///|
/// Score points charged per 10 minutes of average run duration (unit:
/// points per 10 minutes; the 时间 dimension, last in the gradient).
let pick_time_penalty_per_10min : Double = 0.5
///|
/// Minimum benchmark sample count a metrics point must carry; tiny samples
/// must not win on noise.
let pick_min_total : Int = 30
///|
/// The slice of slot metadata pick eligibility needs: which provider owns
/// the slot, which model id metrics points must name, and which efforts the
/// slot advertises.
priv struct PickSlotFacts {
slot_id : String
provider_id : String
model_id : String
thinking_efforts : Array[String]
}
///|
/// One scored metrics point together with the slot it landed on.
priv struct PickCandidate {
point : @devkit.MetricsPoint
slot_id : String
}
///|
/// Amortized tokens per solved problem: the source's average total tokens
/// per run scaled by `total / passed`. Failed runs burn tokens too, so this
/// is the honest "tokens to complete one task": a model that fails often
/// pays for every attempt until one succeeds. `None` when the source stated
/// no token total or when no run solved a problem — such points are
/// ineligible, never zero-filled or estimated.
fn pick_tokens_per_pass(point : @devkit.MetricsPoint) -> Double? {
match point.tokens {
Some(tokens) =>
if point.passed > 0 {
Some(tokens * point.total.to_double() / point.passed.to_double())
} else {
None
}
None => None
}
}
///|
/// Eligible pool for one provider: metrics points whose model names one of
/// the provider's slot models, whose effort that slot advertises, whose
/// benchmark sample clears the noise guard, and that state every scored
/// dimension — the token total (amortizable over a positive pass count) and
/// the run duration. A point missing a scored dimension is skipped, never
/// zero-filled or estimated. Slots sharing provider and model deduplicate
/// (first in slot order wins).
fn pick_eligible_pool(
provider_id : String,
points : Array[@devkit.MetricsPoint],
slots : Array[PickSlotFacts],
) -> Array[PickCandidate] {
let pool : Array[PickCandidate] = []
let claimed : Map[String, Unit] = Map::from_array([])
for slot in slots {
if slot.provider_id != provider_id || claimed.contains(slot.model_id) {
continue
}
claimed[slot.model_id] = ()
for point in points {
if point.model == slot.model_id &&
slot.thinking_efforts.contains(point.effort) &&
point.total >= pick_min_total &&
pick_tokens_per_pass(point) is Some(_) &&
point.minutes is Some(_) &&
point.passed > 0 {
pool.push({ point, slot_id: slot.slot_id, })
}
}
}
pool
}
///|
/// Drop every point another eligible point dominates on the four scored
/// dimensions: Q dominates P when Q's IQ is >=, cost <=, tokens per solved
/// problem <=, and minutes <=, with at least one comparison strict. Such
/// points leave the pool before ranking, so they can never win nor become
/// candidates.
fn pick_dominance_filter(pool : Array[PickCandidate]) -> Array[PickCandidate] {
let kept : Array[PickCandidate] = []
for entry in pool {
let mut dominated = false
match (pick_tokens_per_pass(entry.point), entry.point.minutes) {
(Some(entry_tpp), Some(entry_minutes)) =>
for other in pool {
match (pick_tokens_per_pass(other.point), other.point.minutes) {
(Some(other_tpp), Some(other_minutes)) =>
if other.point.iq >= entry.point.iq &&
other.point.cost_usd <= entry.point.cost_usd &&
other_tpp <= entry_tpp &&
other_minutes <= entry_minutes &&
(
other.point.iq > entry.point.iq ||
other.point.cost_usd < entry.point.cost_usd ||
other_tpp < entry_tpp ||
other_minutes < entry_minutes
) {
dominated = true
break
}
_ => ()
}
}
// Eligibility guarantees both dimensions; an unscorable entry is kept
// (and can never dominate anything).
_ => ()
}
if !dominated {
kept.push(entry)
}
}
kept
}
///|
/// The pick score in IQ points: raw IQ minus the weighted token, cost, and
/// time penalties under the gradient 分数 > tokens > 金钱 > 时间 (weights
/// documented on the constants). Eligibility guarantees both derived
/// dimensions; anything else never reaches ranking and scores on raw IQ.
fn pick_score(point : @devkit.MetricsPoint) -> Double {
match (pick_tokens_per_pass(point), point.minutes) {
(Some(tokens_per_pass), Some(minutes)) =>
point.iq -
pick_token_penalty_per_m * (tokens_per_pass / 1_000_000.0) -
pick_cost_penalty_per_usd * point.cost_usd -
pick_time_penalty_per_10min * (minutes / 10.0)
_ => point.iq
}
}
///|
/// Deterministic pick order: score descending, then cheaper cost first,
/// then model name ascending.
fn pick_order(a : PickCandidate, b : PickCandidate) -> Int {
let score_a = pick_score(a.point)
let score_b = pick_score(b.point)
if score_a != score_b {
return score_b.compare(score_a)
}
if a.point.cost_usd != b.point.cost_usd {
return a.point.cost_usd.compare(b.point.cost_usd)
}
a.point.model.compare(b.point.model)
}
///|
/// Dominance-filtered, score-ranked eligible pool, best first.
fn pick_ranked(pool : Array[PickCandidate]) -> Array[PickCandidate] {
let ranked = pick_dominance_filter(pool)
ranked.sort_by(pick_order)
ranked
}
///|
/// Encode one pick candidate verbatim for the host-side candidate notices:
/// slot/model/effort identity plus the source-stated numbers at full
/// precision (number formatting is presentation, the host's job).
fn pick_candidate_json(slot_id : String, point : @devkit.MetricsPoint) -> Json {
Json::object(
Map::from_array([
("slot_id", Json::string(slot_id)),
("model", Json::string(point.model)),
("effort", Json::string(point.effort)),
("iq", Json::number(point.iq)),
("cost_usd", Json::number(point.cost_usd)),
]),
)
}
///|
/// Run the `/model pick` flow: read the provider's registered
/// metrics, score the eligible slot/effort pairs, auto-switch to the winner
/// mirroring the manual switch branch, and return ranks 2-3 of the filtered
/// pool as candidates. A failed read or an empty eligible pool raises —
/// never a fallback pick.
async fn RouterModelPort::run_provider_pick(
self : RouterModelPort,
provider_id : String,
source : &@devkit.ModelMetricsSource,
) -> @posoco.CommandOutcome raise @posoco.CommandError {
// The async read can also raise (cancellation, timeout); a raised read is
// as unavailable as an Err one and folds into the same failure.
let result = source.read() catch { error => Err(error.to_string()) }
let points = match result {
Ok(points) => points
Err(reason) =>
raise @posoco.CommandError::ExecutionFailed(
"metrics unavailable: " + reason,
)
}
let slots : Array[PickSlotFacts] = []
for slot in self.list_slots() {
slots.push({
slot_id: slot.id,
provider_id: slot.provider_id,
model_id: slot.model_id,
thinking_efforts: slot.thinking_efforts,
})
}
let ranked = pick_ranked(pick_eligible_pool(provider_id, points, slots))
if ranked.is_empty() {
raise @posoco.CommandError::ExecutionFailed(
"no eligible " + provider_id + " models in metrics",
)
}
let winner = ranked[0]
// Validates the effort against the slot and rebuilds it; a mismatch is a
// command failure.
self.select_effort(winner.slot_id, winner.point.effort)
self.active_id = winner.slot_id
self.publish_model_status()
self.publish_provider_event()
// Mirror the manual switch: immediate probe so the bar reflects the new
// provider's quota as soon as the command returns.
self.refresh_quota_now()
let candidates : Array[Json] = []
let mut rank = 2
while rank <= 3 && rank <= ranked.length() {
let entry = ranked[rank - 1]
candidates.push(pick_candidate_json(entry.slot_id, entry.point))
rank = rank + 1
}
@posoco.CommandOutcome::Success(
feedback="auto-picked model slot: " +
winner.slot_id +
" (" +
winner.point.effort +
")",
structured=Some(
Json::object(
Map::from_array([
("provider", Json::string(provider_id)),
("picked", pick_candidate_json(winner.slot_id, winner.point)),
("candidates", Json::array(candidates)),
]),
),
),
ui_hint=Some(@posoco.UiHint::RefreshModelList),
)
}