M0: compilable skeleton — Kigi 0.1.0 fork surgery

Hard fork of xai-org/grok-build (Apache-2.0) re-targeted as Kigi, an
unofficial Kimi Code CLI community build.

Rename & identity
- 72 xai-*/xai-grok-* crates -> kigi-* (explicit: xai-grok-pager-bin ->
  kigi-bin [binary `kigi`], xai-grok-pager -> kigi-tui; rest mechanical);
  ptyctl, ptyctl-cli, third_party/ unchanged; proto package
  xai.grok.tools.v1 -> kigi.tools.v1
- Config home ~/.kigi (KIGI_SHARE_DIR override), env prefix GROK_* ->
  KIGI_*, `kigi --version` carries the unofficial-community-build notice
- clap identity, help text, startup banner, prompt templates rebranded
  (templates re-encrypted)

Deletions (PRD removal list #5/#6/#7/#9/#10)
- voice input (xai-grok-voice) and all TUI wiring
- telemetry: Mixpanel client, external OTel stream, Sentry, OTLP layers,
  trace/GCS/S3 upload queues (kigi-file-utils halved), workspace upload
  module & dc_log, heap-profile uploader, auth-diagnostics uploader,
  session-analytics halves of feedback; local zero-egress observability
  preserved in new kigi-log crate (unified log, --debug firehose,
  subsystem file logs, opt-in instrumentation)
- announcements (crate, remote-settings fields, TUI surfaces)
- plugin marketplace (crate, sources/browse/CTA/extensions-modal tab);
  direct plugin install/uninstall/update via kigi-agent git_install kept
- relay/gateway/assets endpoints and features (agent relay, headless
  relay transport, gateway bridge, LeaderEnvUrls); leader IPC socket now
  ~/.kigi/leader.sock + KIGI_LEADER_SOCKET, no ws-url derivation
- functional types rehomed instead of deleted: PermissionMode ->
  kigi-config-types, McpInitStrategy -> kigi-mcp, PrCreationSource ->
  session signals, TerminalDiagnostics -> kigi-pager-render, agent_id ->
  shell util

Endpoints
- kigi-env rewritten: single production KigiEndpoints {coding_api_base_url
  https://api.kimi.com/coding/v1 (KIGI_CODE_BASE_URL), oauth_host
  https://auth.kimi.com (KIGI_OAUTH_HOST), update_base_url (GitHub
  Releases API), upgrade_page_url}; GrokBuildEnvironment enum deleted

Toolchain & workspace hygiene
- Rust 1.97.0 pinned; edition 2024; full cargo update; git2 hoisted to
  workspace at 0.21 (Option->Result API migration), quick-xml 0.41
- Root Cargo.toml hand-maintained (PRD §8.1): version 0.1.0 inherited by
  all members, members sorted, unused deps pruned
- cargo-deny advisories gate (deny.toml with documented transitive
  exceptions); CI workflow (check/clippy/fmt/deny/test, macOS+Linux)
- cross-crate test seams re-gated behind `test-support` cargo feature;
  insta snapshot baselines renamed to the kigi_tui prefix
- clippy --workspace --all-targets: zero warnings; fmt clean

Fixes surfaced by the port
- updater probe/installer divergence (bin/kigi vs bin/grok symlink set)
- idle model-metadata refresh dead under KIGI_CODE_BASE_URL override
  (new is_effective_coding_endpoint_url, loopback+override aware)
- macOS symlinked-TMPDIR fixture canonicalization (foreign_sessions,
  fast-worktree); RSS measurement tests serialized via serial_test

Docs & legal (Apache §4)
- NOTICE added (upstream attribution + change statement); THIRD-PARTY
  notices sustained; kigi-tools ported-code notices extended; README,
  CONTRIBUTING, SECURITY, AGENTS.md rewritten

Out of scope for M0 (tracked): Kimi auth/inference (M1), search/fetch,
command parity, config import (M2), Computer Hub excision & final
brand-token sweep (M2), distribution & self-update rewrite (M3).
This commit is contained in:
2026-07-17 05:31:01 -04:00
commit d6c20fc13f
2612 changed files with 1353757 additions and 0 deletions
@@ -0,0 +1,247 @@
//! Trigger decision and result types for intra-compaction.
use std::sync::Arc;
use std::time::Duration;
use thiserror::Error;
use super::config::{IntraCompactionConfig, IntraCompactionMode};
/// Information about why intra-compaction was triggered.
///
/// Constructed by [`should_compact`] and threaded through to
/// [`crate::compact`] and the agent's event stream.
#[derive(Debug, Clone)]
pub struct IntraCompactionTrigger {
/// Token count of the prompt most recently sent to the model.
pub last_prompt_tokens: u32,
/// Context window of the agent's current sampler (`max_len`).
pub context_window: u32,
/// `last_prompt_tokens / context_window` as an integer percentage,
/// clamped to [0, 100].
pub percent: u8,
/// Step index (0-based) at which the trigger fired.
pub step: u32,
}
/// Result of a successful compaction.
#[derive(Debug, Clone)]
pub struct IntraCompactionResult {
/// Sum of tokens in the turns that were compacted.
pub tokens_before: u32,
/// Tokens in the resulting compaction turn (the LLM summary).
pub tokens_after: u32,
/// Number of accumulated turns that were replaced.
pub turns_compacted: u32,
/// End-to-end elapsed time (decision → apply).
pub elapsed: Duration,
/// The summary text the LLM produced — the developer-turn content that
/// replaced the compacted turns (for `HistoryThenSteps`, both passes'
/// summaries joined). Carried so callers can record the actual result
/// (e.g. as a developer turn in the thinking trace). `Arc<str>` because the
/// summary can be large and is cloned along with the event downstream.
pub summary: Arc<str>,
}
/// Errors that can occur during intra-compaction.
///
/// All errors are non-fatal — the caller should log and continue without
/// compaction. Worst case the next sampling call may fail with 400, which
/// is the same as today (no compaction support at all).
#[derive(Debug, Error)]
pub enum IntraCompactionError {
/// The accumulated turn list has nothing meaningful to compact.
/// Triggered when:
/// - `get_accumulated_turns_for_compaction()` returns empty
/// - `select_turns_to_compact()` finds nothing reducible (below
/// `min_compactable_tokens` or no safe split point)
#[error("nothing to compact")]
NothingToCompact,
/// The compaction LLM call timed out with no usable output.
#[error("compaction LLM call timed out")]
Timeout,
/// The compaction LLM returned an empty response.
#[error("compaction LLM returned empty response")]
EmptyResponse,
/// Compaction result was not smaller than the original by the configured
/// minimum (`max_reduction_ratio`).
#[error("insufficient reduction: {tokens_after} > {tokens_before} * ratio")]
InsufficientReduction {
tokens_before: u32,
tokens_after: u32,
},
/// `apply_steps_compaction` received an invalid `n_turns_to_remove`
/// (greater than the current accumulated-turn count). Parser state is
/// left unchanged.
#[error("invalid split: requested {requested}, only {available} available")]
InvalidSplit { requested: usize, available: usize },
/// The parser variant does not support intra-compaction.
#[error("intra-compaction not supported by this parser variant")]
Unsupported,
/// LLM sampler construction failed.
#[error("compaction sampler build failed: {0}")]
SamplerBuild(String),
/// LLM sampler call could not be started.
#[error("compaction sampler start failed: {0}")]
SamplerStart(String),
/// LLM sampler emitted an error mid-stream.
#[error("compaction sampler error: {0}")]
SamplerStream(String),
/// `apply_steps_compaction` failed for a parser-specific reason
/// (e.g. SglangEngine rebuild error).
#[error("apply failed: {0}")]
Apply(String),
}
/// Pure decision function: should intra-compaction trigger now?
///
/// Returns `Some(trigger)` if all gating conditions are met; `None` otherwise.
/// Caller must additionally check the feature flag and/or any global kill
/// switch — this function deals only with the policy + step state.
///
/// `min_steps_before_compact` remains on [`IntraCompactionConfig`] for every
/// mode, but is **not** enforced when
/// [`mode`](IntraCompactionConfig::mode) is
/// [`IntraCompactionMode::FullReplace`] — that path matches grok-build's
/// full-replace trigger (token threshold alone) so a large first-step prompt
/// can still compact. Partial modes still gate on min steps.
pub fn should_compact(
policy: &IntraCompactionConfig,
last_prompt_tokens: u32,
context_window: u32,
current_step: u32,
) -> Option<IntraCompactionTrigger> {
if !policy.enabled {
return None;
}
if context_window == 0 {
return None;
}
// FullReplace: token threshold only (field still present on config).
// Partial modes: skip early steps with little content to reduce.
if policy.mode != IntraCompactionMode::FullReplace
&& current_step < policy.min_steps_before_compact
{
return None;
}
let threshold = (context_window as u64 * policy.trigger_threshold_percent as u64 / 100) as u32;
if last_prompt_tokens <= threshold {
return None;
}
let percent = (last_prompt_tokens as u64 * 100 / context_window as u64).min(100) as u8;
Some(IntraCompactionTrigger {
last_prompt_tokens,
context_window,
percent,
step: current_step,
})
}
#[cfg(test)]
mod tests {
use super::*;
fn enabled_policy() -> IntraCompactionConfig {
IntraCompactionConfig {
enabled: true,
// Default mode is FullReplace — min_steps stored but not enforced.
trigger_threshold_percent: 85,
target_threshold_percent: 50,
min_steps_before_compact: 3,
..Default::default()
}
}
fn enabled_partial_policy(mode: IntraCompactionMode) -> IntraCompactionConfig {
IntraCompactionConfig {
mode,
..enabled_policy()
}
}
#[test]
fn returns_none_when_disabled() {
let mut p = enabled_policy();
p.enabled = false;
assert!(should_compact(&p, 90_000, 100_000, 10).is_none());
}
#[test]
fn returns_none_when_below_threshold() {
let p = enabled_policy();
// 84% of 100K = 84_000, threshold 85% = 85_000.
assert!(should_compact(&p, 84_000, 100_000, 10).is_none());
}
#[test]
fn returns_some_when_above_threshold() {
let p = enabled_policy();
let t = should_compact(&p, 90_000, 100_000, 10).expect("should trigger");
assert_eq!(t.last_prompt_tokens, 90_000);
assert_eq!(t.context_window, 100_000);
assert_eq!(t.percent, 90);
assert_eq!(t.step, 10);
}
#[test]
fn full_replace_keeps_field_but_ignores_min_steps() {
let p = enabled_policy();
assert_eq!(p.mode, IntraCompactionMode::FullReplace);
assert_eq!(p.min_steps_before_compact, 3);
// Field is present; FullReplace only uses the token threshold
// (parity with grok-build auto-compact).
let t = should_compact(&p, 90_000, 100_000, 0).expect("should trigger");
assert_eq!(t.step, 0);
assert!(should_compact(&p, 90_000, 100_000, 2).is_some());
}
#[test]
fn partial_modes_enforce_min_steps() {
for mode in [
IntraCompactionMode::StepsOnly,
IntraCompactionMode::HistoryOnly,
IntraCompactionMode::HistoryThenSteps,
] {
let p = enabled_partial_policy(mode);
assert!(
should_compact(&p, 90_000, 100_000, 2).is_none(),
"{mode:?} should gate on min_steps"
);
let t = should_compact(&p, 90_000, 100_000, 3).expect("should trigger at min steps");
assert_eq!(t.step, 3);
}
}
#[test]
fn returns_none_when_context_window_zero() {
let p = enabled_policy();
assert!(should_compact(&p, 1_000, 0, 10).is_none());
}
#[test]
fn percent_caps_at_100() {
let p = enabled_policy();
let t = should_compact(&p, 200_000, 100_000, 10).expect("should trigger");
assert_eq!(t.percent, 100);
}
#[test]
fn boundary_exact_threshold_does_not_trigger() {
let p = enabled_policy();
// last_prompt_tokens == threshold: not strictly greater than.
assert!(should_compact(&p, 85_000, 100_000, 10).is_none());
// One above triggers.
assert!(should_compact(&p, 85_001, 100_000, 10).is_some());
}
}