/** * Per-run model selection & role-based routing. * * ADR-0017 consequence: role-based model routing (different run kinds default * to different models) is a **product/admin configuration** concern, not a spec * invariant. This registry is the seam for that config; the concrete policy * (which models are admin-enabled, which role maps to which default) is `OPEN` * here — decided by admin settings + ADR, not hard-coded. */ /** Coarse run role, used to pick a default model. Open set: add as product grows. */ export type RunRole = "draft" | "review" | "triage"; /** A model the admin has enabled for use by the Hub. */ export interface ModelEntry { readonly id: string; /** Human label for the teacher-side switcher UX. */ readonly label: string; /** True when the model is known to support tool use reliably. */ readonly toolCapable: boolean; } export interface ModelRegistry { /** All models admin-enabled for this Hub instance. */ list(): readonly ModelEntry[]; /** Default model id for a given run role, if a routing rule exists. */ defaultFor(role: RunRole): string | undefined; } /** * A simple in-memory registry. Real wiring reads from admin settings / DB; this * is the skeleton seam. The policy (role→model map) is intentionally pluggable. */ export class InMemoryModelRegistry implements ModelRegistry { private readonly models: readonly ModelEntry[]; private readonly defaults: Map; constructor(models: readonly ModelEntry[], defaults: Partial> = {}) { this.models = models; this.defaults = new Map( (Object.entries(defaults) as [RunRole, string][]).filter(([, v]) => v !== undefined), ); } list(): readonly ModelEntry[] { return this.models; } defaultFor(role: RunRole): string | undefined { return this.defaults.get(role); } /** Resolve a model id, falling back to the role default, then the first enabled. */ resolve(requested: string | undefined, role: RunRole): string { if (requested !== undefined && this.models.some((m) => m.id === requested)) { return requested; } const d = this.defaultFor(role); if (d !== undefined) return d; const first = this.models[0]; if (first === undefined) throw new Error("no models enabled for this Hub"); return first.id; } }