d6e49bcc7db97de10156e3adc2e2d4781f68cb79
7
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f825132983 |
Add Cerebras platform + generalize StrictOpenAi dialect (provider 10)
The 13th registry row: id "cerebras", CEREBRAS_API_KEY > auth.json "cerebras" scope, https://api.cerebras.ai/v1 with KIGI_CEREBRAS_BASE_URL override, Bearer, ChatCompletions, enrichment-backed metadata (models_dev_id cerebras). Cerebras' catalog is all chat LLMs (no embedding/tts pollution) and its /models is minimal (ids only), so restrict_to_enriched=FALSE: keep every live model, enrich the known ones (context + effort menus low/medium/high), unknown ones keep the default context. The e2e pins this enrich-without- restrict path (new — prior enrichment providers all used restrict=true). Review caught a likely-DOA defect: Cerebras uses strict additionalProperties:false validation (confirmed 400-rejecting store, maxTokens, thinking, nested reasoning_content), and stream_options is not in its schema — so Passthrough (which keeps the stream_options.include_usage kigi injects on every streaming request) would very likely 400 all streaming. Generalized ChatCompat::Mistral -> ChatCompat::StrictOpenAi (serde alias "mistral" keeps pre-rename persisted sessions loading), which strips stream_options + private fields for any strict OpenAI-compat validator; both Mistral and Cerebras now map to it. Future strict-validator candidates (NVIDIA/Azure/Xiaomi/OpenCode) noted for the same check. reasoning_effort (incl. "none") passes through; /v1/models requires auth so key validation works; console cloud.cerebras.ai. |
||
|
|
9953a26b8d |
Add Mistral platform + Mistral dialect + array-content handling (provider 5)
The 8th registry row: id "mistral", MISTRAL_API_KEY > auth.json "mistral" scope, https://api.mistral.ai/v1 with KIGI_MISTRAL_BASE_URL override, enrichment-backed metadata with the tool-calling listing restriction (embed/moderation/OCR noise). Mistral is NOT a pure-pattern provider — an adversarial review found two doc-confirmed blockers that no test exercises (no e2e covers a chat POST), so the gate-green registry row alone would have shipped it DOA. A research workflow pinned the exact wire shapes against the mistralai/client-python SDK source (adversarially verified), then both were fixed: 1. stream_options 422: Mistral's strict Pydantic validator rejects the stream_options.include_usage field kigi injects on every streaming request (the SDK's request model has no such field). New ChatCompat::Mistral dialect strips it (plus the kigi-private message fields, like Passthrough). Streaming usage falls back to token estimation. 2. Reasoning content arrays: Mistral reasoning models return content as Union[str, List[ContentChunk]] on both streaming and non-streaming, which the flat Option<String> path could not decode -> aborted turn. A UNIVERSAL lenient deserializer (#[serde(from = "Raw..")] on ChatResponseMessage + ChatChunkDelta) accepts string-or-array, routing {type:text} chunks to the answer and the nested text of {type:thinking} chunks to reasoning_content, tolerant of the OPEN chunk union (unknown types ignored, never fatal). String content stays byte-identical for every other provider (kimi/deepseek/groq/BYOK). Review refuted all seven attack lines (no regression, no crash, exhaustive) and flagged one coverage gap, now closed: a stream-consumer integration test drives a full thinking -> transition -> answer chunk sequence and proves it yields the same reasoning-sibling + assistant-answer result as the reasoning_content string path. Also folds a verified quirk matrix for all 23 remaining API providers into providers-plan.md, tiered by real difficulty (self-enriching OpenRouter/ Vercel; bare-array Together listing; Messages-dialect MiniMax reusing the Anthropic machinery; non-Bearer Azure/Bedrock; router wildcards; the OAuth block). |
||
|
|
7efb4b07cc |
Add DeepSeek platform + ChatCompletions dialect system (provider 3)
The 6th registry row: id "deepseek", DEEPSEEK_API_KEY > auth.json "deepseek" scope, base https://api.deepseek.com (chat rides {base}/chat/completions per official docs) with KIGI_DEEPSEEK_BASE_URL override, enrichment-backed metadata (1M context, 384k output cap, high/max effort menu). Structural fix the cycle exposed: kigi's Kimi-specific body adaptation ran UNCONDITIONALLY on every ChatCompletions request. New ChatCompat dialect, declared per platform row and threaded through SamplerConfig, ClientDefaults, and the session-persisted SamplingConfig (serde-default Kimi keeps restored pre-field sessions and BYOK endpoints byte-identical; production persist seams copy it; subagents inherit it): - Kimi: full legacy pipeline (dispatch ≡ legacy pinned) - DeepSeek: thinking:{type, reasoning_effort} per api-docs.deepseek.com (server maps low/medium→high, xhigh→max itself; none disables; absent leaves the server default) - Passthrough: OpenAI-style reasoning_effort scalar untouched (unblocks Groq and the rest of the OpenAI-compatible list) Review-confirmed release blocker fixed: kigi replays Kimi's reasoning_content (and its private model_id) on input assistant messages — Kimi consumes these, but DeepSeek documents input reasoning_content as prefix-mode-only (historically a 400) and other providers don't know either field. The DeepSeek and Passthrough arms now strip both; Kimi's own pipeline is untouched. Pinned on both message shapes. |
||
|
|
83e6935189 |
Split canonical ReasoningEffort::Max out of Xhigh (providers P0c-1)
OpenAI (Responses) and Anthropic (Messages) treat xhigh and max as
DISTINCT effort levels in 2026, and the Kimi K3 wire's top tier is max —
the old parse alias (max→Xhigh) conflated them. Canonical Max now exists:
parse/as_str/serde split, Messages mapping sends xhigh and max as their
own tokens (was Xhigh→"max"), and the K3 menu token max carries
canonical Max end to end.
Kimi wire is byte-identical in all four flows (menu pick, restored
legacy xhigh session, --reasoning-effort flag, /effort command) —
adversarially traced and pinned: kimi_compat's string-level xhigh→max
rename covers legacy tokens, max passes through verbatim.
From the review:
- Rollback safety: persisted reasoning_effort (session summaries, chat
history) deserializes leniently — unknown future tokens degrade to
None with a warning instead of hiding sessions or failing resume.
- Restore migration: a pre-split xhigh override onto a model whose menu
offers max but not xhigh (K3) migrates once, healing display/active-row
drift and re-persisting the live vocabulary.
- /effort max now rejects (with the offered list) on models whose menu
lacks a max row instead of silently applying xhigh; deliberate, tested.
- The interim Responses-backend Max→xhigh downgrade (async-openai has no
Max variant through 0.41) warns loudly; real max wiring lands with the
OpenAI provider cycle via post-serialize body patch.
- Two rusted ignored-e2e wire pins asserted the pre-adapt reasoning_effort
key (deleted by the body adapter since
|
||
|
|
6f31415ed6 |
§9 acceptance: grep-zero sweep — every internal x.ai/grok identifier renamed
The PRD's first acceptance gate now holds: grep -RinE '\bx\.ai\b|grok' crates/ --include='*.rs' → 0 matches (exempt: NOTICE and third-party license archives, README provenance, and the required 'Based on Grok Build Open Source' attribution, now sourced from version_attribution.txt). Wire-visible renames (both sides in this repo, changed in lockstep): - Auth method id 'grok.com' → 'kimi-code' (AuthMethodKind::KimiCode). - Every x.ai/* and _x.ai/* ACP ext method and meta key → kigi/* / _kigi/* (~200 names; grokShell → kigiShell). Session-file replay keeps a read-side alias for the legacy '_x.ai/session/update' method so existing updates.jsonl histories load; writes emit only the new name (both directions test-pinned). - Agent types grok-build* → kigi* with a documented legacy-prefix alias at resolution time so persisted sessions keep resolving. - ToolNamespace/BuiltinAgentName GrokBuild* → Kigi* (wire snake_case kigi/kigi_concise/kigi_hashline; schema regenerated); grok_build implementation dirs renamed to kigi*. - x-grok-* headers → x-kigi-*, __GROK_* sentinels → __KIGI_*, themes grokday/groknight → kigiday/kiginight (old persisted values fall back to the default theme), web_fetch allowlist xAI hosts → kimi.com + moonshot platforms, changelog CDN → this repo, grok-build changelog archives deleted. - BYOK default endpoint removed: [endpoints] api_base_url is now truly optional with NO default — consumers fail fast with the flag name when unset (no silent x.ai egress). Mock harnesses inject it explicitly. - System-prompt identity fixed: 'released by xAI' → 'an unofficial community CLI for Kimi' (template + regenerated encrypted form). Also repaired pre-existing grok-era test debt found by the sweep: the stale trace_classify default-model pin, the grok-pager UA label test, pty-harness stale-binary reuse and non-hermetic moonshot routing (a PTY test could previously reach the real api.moonshot.cn), and the outdated oauth fixture scope key. Gates: §9 grep 0; fmt clean; workspace check/clippy 0/0 (-D warnings); FULL cargo test --workspace: 234 suites, 21,961 passed, 0 failed; deny advisories ok. |
||
|
|
5f3f9509b9 |
Wire K3 thinking-effort levels end to end (fixes 'model does not support reasoning effort')
The live /models wire (verified against api.kimi.com) marks every Kimi
Code model supports_thinking_type: "only" and gives K3 a think_efforts
block {support, valid_efforts: [low, high, max], default_effort: max} —
both of which the F4 sync discarded, hardcoding
supports_reasoning_effort: false. Every effort selection was therefore
rejected with 'current model does not support reasoning effort'.
- kigi-models: WireModel gains supports_thinking_type + WireThinkEfforts;
"only" forces the always_thinking capability.
- models_fetch: think_efforts maps into the catalog entry — wire tokens
stay the option ids/labels (max/Max), canonical values map via the
ReasoningEffort parser (max → Xhigh), default_effort marks the default.
This lights up the existing /model <model> [effort] two-phase completion
and the /effort menu with the server's own vocabulary.
- kimi_compat: the effort level rides the wire as thinking.effort
({"type": "enabled", "effort": "low"} is accepted live; invalid
levels are a 400). Only the canonical-vs-wire spelling divergence
(xhigh → max) is renamed; levels pass through verbatim so a contract
violation surfaces instead of being clamped away.
Live acceptance: kigi -m kimi-code/k3 --reasoning-effort max -p ... round
trips against api.kimi.com, and the refreshed models_cache.json carries
low/high/max with the max default.
|
||
|
|
ea0ce9d15f |
F3: Kimi inference pipeline + full grok cloud-surface excision
Sampler / inference (PRD F3):
- kimi_compat.rs: single adaptation point for the Kimi chat/completions
dialect (thinking-field mapping, model_id stripping, empty-content
tool-call message fix, stream_options.include_usage), with kimi-cli
source citations
- Rate-limit handling reworked for Kimi/Moonshot semantics; UA kigi/{version}
- /models replaces the xAI models-v2 endpoint everywhere; idle model
refresh carries X-Msh-* device headers only (X-XAI-Token-Auth and
x-grok-client-mode/CLIENT_MODE_HEADER machinery deleted)
Cloud-surface excision (PRD §5, zero-egress):
- remote/ conversations lane, cli-chat-proxy-types crate, prod/ dir,
share command, credit bar: deleted (single local session lane;
paginate() replaces merge_and_paginate)
- Subscription/tier gate stack deleted end-to-end: AppView
gate/tier/team/ZDR fields, app/subscription.rs watch loop,
dispatch/billing.rs paywall + SuperGrok upsell, free-usage-exhausted
chain, tier-restricted commands, GateInfo, RemoteSettings gate fields,
SettingsUpdateNotification gate fields
- /privacy + coding-data-sharing setting deleted (backed by a dead xAI
RPC; Kigi is zero-egress — nothing to share or retain remotely)
Auth UX correctness (user-reported):
- Device-flow fixtures now mirror the live Kimi payload shape
(https://www.kimi.com/code/authorize_device?user_code=..., verified
against auth.kimi.com); the fabricated auth.kimi.com/device?code=...
URLs are gone
- open_browser_detached is a no-op under cfg(test): unit tests drove
wiremock fixture URLs into the real browser (root cause of the
"garbage mock link" ABCD-1234 tabs)
- Welcome/pager-minimal rebrand: Grok Build -> Kigi, grok.com ->
kimi.com, "Sign in to Grok" -> "Sign in to Kimi"
|