Add models.dev metadata-enrichment pipeline (providers P0c-2)
Provider /models listings that return bare ids (OpenAI-style) get context windows, thinking levels, image support, and display names from models.dev: kigi-models owns the transform (parse_api_json — ONE field interpretation for the bundled snapshot AND runtime refreshes), enrich_wire_model fills gaps with wire values always winning and model availability strictly wire-truth. Spec rows gained models_dev_id + wire_serves_metadata; all three current platforms are wire-served, so this pipeline is provably inert for them (byte-identical catalogs, zero egress, zero ~/.kigi writes — adversarially verified). Shell side: enrichment_fetch with a 24h disk cache guarded by binary version + keep-set + future-stamp sanity (a registry change or downgrade refetches instead of serving a catalog missing new providers), refresh of https://models.dev/api.json filtered to registry ids, KIGI_MODELS_DEV_URL override with case/whitespace-tolerant kill switch, fallback chain fresh-cache > refresh > stale-cache > bundled (each step logged). The fast path returns an empty catalog without forcing the bundled parse. From the review: blast-radius-confined parsing (one drifted provider on models.dev warn-skips instead of failing the whole refresh), registry- coverage and field-coverage tests guarding script/parser drift, a path- injectable core with 8 state-machine tests (one of which caught a guard patch that had failed to apply), _meta provenance stamp in the snapshot, and models.dev (MIT) attribution in NOTICE. Snapshot: 29 providers, 1124 models, 246KB, regenerated by scripts/gen_enrichment_snapshot.py (pure filter, no transform).
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
use std::sync::LazyLock;
|
||||
|
||||
pub mod enrichment;
|
||||
|
||||
// ── Platform registry (PRD F2) ──────────────────────────────────────────────
|
||||
|
||||
/// Env var holding the moonshot-cn API key (wins over the generic name).
|
||||
@@ -82,6 +84,13 @@ struct PlatformSpec {
|
||||
console_host: Option<&'static str>,
|
||||
/// Interactive login-picker label. `None` = fall back to `display_name`.
|
||||
login_label: Option<&'static str>,
|
||||
/// This platform's provider id on models.dev, for metadata enrichment.
|
||||
/// `None` = not covered there (enrichment silently skips).
|
||||
models_dev_id: Option<&'static str>,
|
||||
/// True when the platform's `/models` listing itself serves context
|
||||
/// window / thinking metadata — enrichment (and its network refresh) is
|
||||
/// skipped entirely for such platforms.
|
||||
wire_serves_metadata: bool,
|
||||
}
|
||||
|
||||
const KIMI_CODE_SPEC: PlatformSpec = PlatformSpec {
|
||||
@@ -94,6 +103,8 @@ const KIMI_CODE_SPEC: PlatformSpec = PlatformSpec {
|
||||
vendor: "Kimi",
|
||||
console_host: None,
|
||||
login_label: None,
|
||||
models_dev_id: Some("kimi-for-coding"),
|
||||
wire_serves_metadata: true,
|
||||
};
|
||||
|
||||
const MOONSHOT_CN_SPEC: PlatformSpec = PlatformSpec {
|
||||
@@ -109,6 +120,8 @@ const MOONSHOT_CN_SPEC: PlatformSpec = PlatformSpec {
|
||||
vendor: "Moonshot",
|
||||
console_host: Some("platform.moonshot.cn"),
|
||||
login_label: Some("Moonshot Open Platform (API key \u{b7} moonshot.cn)"),
|
||||
models_dev_id: Some("moonshotai-cn"),
|
||||
wire_serves_metadata: true,
|
||||
};
|
||||
|
||||
const MOONSHOT_AI_SPEC: PlatformSpec = PlatformSpec {
|
||||
@@ -124,6 +137,8 @@ const MOONSHOT_AI_SPEC: PlatformSpec = PlatformSpec {
|
||||
vendor: "Moonshot",
|
||||
console_host: Some("platform.moonshot.ai"),
|
||||
login_label: Some("Moonshot Open Platform (API key \u{b7} moonshot.ai)"),
|
||||
models_dev_id: Some("moonshotai"),
|
||||
wire_serves_metadata: true,
|
||||
};
|
||||
|
||||
/// The platform registry. Platforms are compiled-in spec rows; there is no
|
||||
@@ -217,6 +232,17 @@ impl PlatformId {
|
||||
pub fn login_label(self) -> &'static str {
|
||||
self.spec().login_label.unwrap_or(self.spec().display_name)
|
||||
}
|
||||
|
||||
/// This platform's provider id on models.dev (metadata enrichment).
|
||||
pub fn models_dev_id(self) -> Option<&'static str> {
|
||||
self.spec().models_dev_id
|
||||
}
|
||||
|
||||
/// True when the live `/models` wire serves metadata itself — enrichment
|
||||
/// and its network refresh are skipped for such platforms.
|
||||
pub fn wire_serves_metadata(self) -> bool {
|
||||
self.spec().wire_serves_metadata
|
||||
}
|
||||
}
|
||||
|
||||
/// Split a managed catalog key `{platform_id}/{model_id}` back into its
|
||||
|
||||
Reference in New Issue
Block a user