M1/F2+F4: platform registry, Moonshot API-key channel, dynamic model sync

F2 — fixed three-platform registry in kigi-models: kimi-code
(subscription, OAuth bearer, base kigi_env::coding_api_base_url()),
moonshot-cn (https://api.moonshot.cn/v1), moonshot-ai
(https://api.moonshot.ai/v1) with kimi-k model-prefix filtering.
Moonshot API keys via KIGI_MOONSHOT_CN_API_KEY / KIGI_MOONSHOT_AI_API_KEY
(+ KIGI_MOONSHOT_API_KEY shared fallback) or ~/.kigi/config.toml;
values redacted from logs/display.

F4 — model catalog now syncs from GET {base}/models (Bearer auth,
wire shape per official kimi-cli: id/context_length/supports_reasoning/
supports_image_in/supports_video_in/display_name) with the official
capability-derivation rules (thinking / always_thinking-in-name /
kimi-k2 implicit set). Managed keys {platform_id}/{model_id}; default
model = first list entry; default thinking iff capabilities contain
thinking/always_thinking. Sync failure → last cache; no cache →
built-in fallback table seeded from ids sourced in official kimi-cli
(kimi-for-coding, kimi-k2-turbo-preview, kimi-k2-thinking-turbo).
401 during sync forces one token refresh and retries.

Model resolution priority preserved: CLI > env > config > server >
fallback. Grok model artifacts (grok-4*/grok-build catalog, tier
gating remnants) removed from non-test code.

All first-party endpoints re-verified live: device_authorization mints
real codes; /models on all three platforms answers with real API auth
errors when unauthenticated.

Gates: check/clippy --all-targets 0/0, fmt clean, deny ok,
kigi-shell lib 5136 green, kigi-tui lib 6819 green, kigi-models 8.
This commit is contained in:
2026-07-17 09:23:44 -04:00
parent 021b82443d
commit fe1f885bb3
25 changed files with 2148 additions and 430 deletions
+4 -5
View File
@@ -537,7 +537,7 @@ pub struct ModelOverrideConfig {
pub web_search: String,
/// `None` = current model.
pub session_summary: Option<String>,
/// Compiled default (`grok-build`) when unset locally, remotely, and via env.
/// Compiled default (`kigi_models::default_model()`) when unset locally, remotely, and via env.
pub image_description: Option<String>,
/// Next-prompt suggestion model pin. Unlike the other overrides this does
/// NOT fill a compiled default — see [`PromptSuggestModelPin`].
@@ -561,10 +561,9 @@ impl Default for ModelOverrideConfig {
/// Unlike the other auxiliary overrides this does not collapse to a plain
/// model string: the consumer (`handle_suggest_prompt`) must distinguish
/// an explicit pin from "unpinned" (where the client hint and the built-in
/// `grok-build-0.1` default apply), and whether the pin came from the env
/// default apply), and whether the pin came from the env
/// escape hatch. Every effective model except an env pin is catalog-guarded —
/// when the model is not in the shell's catalog (e.g. `grok-build-0.1` for
/// OAuth users, whose catalogs exclude it) the per-turn suggestion request is
/// when the model is not in the shell's catalog the per-turn suggestion request is
/// skipped entirely rather than fired doomed. The env pin is deliberately
/// exempt so `KIGI_PROMPT_SUGGESTIONS_MODEL` keeps working for models a
/// catalog does not list (mirrors the pager, which forwards the env value
@@ -596,7 +595,7 @@ fn non_empty_model_override(value: Option<&str>) -> Option<String> {
impl ModelOverrideConfig {
/// CLI flag > env var > config.toml > remote settings > compiled default.
/// `image_description` and `session_summary` always resolve to `Some(_)`
/// (default `grok-build`), never the session model.
/// (the bundled default model), never the session model.
/// `prompt_suggestion` resolves to a [`PromptSuggestModelPin`] instead of
/// a model string (no CLI flag; the default and the catalog guard live at
/// the consumer, `handle_suggest_prompt`).