Turn machinery refactored so the upcoming serve front door reuses it
instead of copying it: the round loop is now runTurn over arbitrary
message history with an optional tool palette and forwarded max_tokens/
temperature. The serve path (ServeTurn) is stateless chat over client
history with tools hard-off: a tool call the model produces anyway is
refused as a tool result, never executed. Also exposes the model router
(so serve can build its catalog) and a sorted class list; llm requests
can now carry temperature.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
80 lines
2.4 KiB
Go
80 lines
2.4 KiB
Go
// Package models implements MODEL ROUTING v0: a static, config-only map from
|
|
// task class -> tier alias -> concrete proxy model. There is deliberately no
|
|
// heuristic code: the tier map in harness.toml is the whole contract, and an
|
|
// unknown class is a hard error so routing stays auditable.
|
|
package models
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
)
|
|
|
|
// Router resolves task classes to concrete model names.
|
|
type Router struct {
|
|
tiers map[string]string // tier alias -> concrete model
|
|
classes map[string]string // task class -> tier alias
|
|
defaultTier string
|
|
}
|
|
|
|
// Decision records one routing outcome for the REPORT trail.
|
|
type Decision struct {
|
|
Class string
|
|
Tier string
|
|
Model string
|
|
}
|
|
|
|
// NewRouter validates the config maps and returns a Router.
|
|
func NewRouter(tiers, classes map[string]string, defaultTier string) (*Router, error) {
|
|
if len(tiers) == 0 {
|
|
return nil, fmt.Errorf("models: tier map is empty")
|
|
}
|
|
if _, ok := tiers[defaultTier]; !ok {
|
|
return nil, fmt.Errorf("models: default tier %q has no model entry", defaultTier)
|
|
}
|
|
for class, tier := range classes {
|
|
if _, ok := tiers[tier]; !ok {
|
|
return nil, fmt.Errorf("models: class %q points at unknown tier %q", class, tier)
|
|
}
|
|
}
|
|
return &Router{tiers: tiers, classes: classes, defaultTier: defaultTier}, nil
|
|
}
|
|
|
|
// Resolve maps a task class to its tier and concrete model. An empty class
|
|
// falls back to the default tier; an unknown class is an error.
|
|
func (r *Router) Resolve(class string) (Decision, error) {
|
|
tier := r.defaultTier
|
|
if class != "" {
|
|
t, ok := r.classes[class]
|
|
if !ok {
|
|
return Decision{}, fmt.Errorf("models: unknown task class %q (add it to [models.classes] in harness.toml)", class)
|
|
}
|
|
tier = t
|
|
}
|
|
model, ok := r.tiers[tier]
|
|
if !ok {
|
|
return Decision{}, fmt.Errorf("models: tier %q has no model entry", tier)
|
|
}
|
|
return Decision{Class: class, Tier: tier, Model: model}, nil
|
|
}
|
|
|
|
// Tiers returns the sorted tier aliases known to the router.
|
|
func (r *Router) Tiers() []string {
|
|
out := make([]string, 0, len(r.tiers))
|
|
for k := range r.tiers {
|
|
out = append(out, k)
|
|
}
|
|
sort.Strings(out)
|
|
return out
|
|
}
|
|
|
|
// Classes returns the sorted task classes known to the router (the
|
|
// `harness serve` model catalog is derived from it: one model per class).
|
|
func (r *Router) Classes() []string {
|
|
out := make([]string, 0, len(r.classes))
|
|
for k := range r.classes {
|
|
out = append(out, k)
|
|
}
|
|
sort.Strings(out)
|
|
return out
|
|
}
|