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:
ZacharyZhang-NY committed 2026-07-17 05:31:01 -04:00
commit d6c20fc13f
2612 files changed
+1353757

No files matched your search

+173
View File
@@ -0,0 +1,173 @@
//! Tip renderer.
use ratatui::{
buffer::Buffer,
layout::Rect,
style::{Color, Modifier, Style},
text::{Line, Span},
widgets::{Paragraph, Widget, Wrap},
};
use crate::render::SafeBuf;
use crate::theme::Theme;
/// Compute the number of rows a tip needs when rendered at the given `width`.
pub fn tip_height(width: u16, tip: &str) -> u16 {
if width == 0 {
return 0;
}
let line = tip_line(tip);
let line_width = line.width() as u16;
if line_width <= width {
1
} else {
// Ceiling division — word wrapping may use slightly more rows than
// a naive character split, but this is a close-enough upper bound.
(line_width as u32)
.div_ceil(width as u32)
.min(u16::MAX as u32) as u16
}
}
fn tip_line(tip: &str) -> Line<'_> {
let theme = Theme::current();
Line::from(vec![
Span::styled(
"Tip: ",
Style::default().fg(theme.gray).add_modifier(Modifier::BOLD),
),
Span::styled(tip, Style::default().fg(theme.gray)),
])
}
/// Render a tip into the provided area, word-wrapping if it exceeds the width.
pub fn render_tip(area: Rect, buf: &mut Buffer, tip: &str) {
if area.height == 0 {
return;
}
let theme = Theme::current();
Paragraph::new(tip_line(tip))
.style(Style::default().bg(theme.bg_base))
.wrap(Wrap { trim: false })
.render(area, buf);
}
/// Blank every cell of `area` (chars, colors, and modifiers) in `color`.
///
/// Modifiers MUST be reset here: ratatui's `Cell::set_style` only *merges*
/// modifiers (`insert(add)` / `remove(sub)`), so a later paint whose style
/// carries no `sub_modifier` inherits whatever BOLD/ITALIC/… an earlier
/// same-frame paint left behind (e.g. the welcome tip's bold `Tip: ` prefix
/// bleeding into the ephemeral tip as "**Queue**d · Enter to send now").
fn clear_rect(buf: &mut Buffer, area: Rect, color: Color) {
for row in 0..area.height {
for col in 0..area.width {
if let Some(cell) = buf.cell_mut((area.x + col, area.y + row)) {
cell.set_char(' ');
cell.fg = color;
cell.bg = color;
cell.modifier = Modifier::empty();
}
}
}
}
/// Render a pre-styled tip line into the banner rect. The whole rect is
/// cleared first (it can be taller than one row when a wrapped session tip
/// reserved it) and the line paints on the first row, truncated at width.
pub fn render_ephemeral_tip(area: Rect, buf: &mut Buffer, line: &Line<'static>) {
if area.height == 0 || area.width == 0 {
return;
}
let theme = Theme::current();
clear_rect(buf, area, theme.bg_base);
buf.set_line_safe(area.x, area.y, line, area.width);
}
#[cfg(test)]
mod tests {
use super::*;
fn row_text(buf: &Buffer, area: Rect, y: u16) -> String {
(0..area.width)
.map(|x| buf.cell((area.x + x, y)).expect("cell in area").symbol())
.collect()
}
#[test]
fn clears_full_rect_and_truncates_to_width() {
let area = Rect::new(0, 0, 8, 2);
let mut buf = Buffer::empty(area);
// Pre-dirty both rows to simulate stale banner content underneath.
buf.set_string(0, 0, "XXXXXXXX", Style::default());
buf.set_string(0, 1, "XXXXXXXX", Style::default());
let line = Line::from("0123456789"); // wider than the rect
render_ephemeral_tip(area, &mut buf, &line);
assert_eq!(row_text(&buf, area, 0), "01234567", "truncated at width");
assert_eq!(
row_text(&buf, area, 1),
" ",
"stale rows below the line are cleared"
);
}
#[test]
fn zero_sized_area_is_a_noop() {
let area = Rect::new(0, 0, 8, 1);
let mut buf = Buffer::empty(area);
buf.set_string(0, 0, "XXXXXXXX", Style::default());
render_ephemeral_tip(Rect::new(0, 0, 8, 0), &mut buf, &Line::from("tip"));
assert_eq!(row_text(&buf, area, 0), "XXXXXXXX", "untouched");
}
/// Regression: a bold underpaint in the banner rect (e.g. the welcome
/// tip's `Tip: ` prefix painted the same frame) must not bleed BOLD into
/// the ephemeral tip. `Cell::set_style` merges modifiers, so the clear
/// pass has to reset them explicitly — otherwise `Queued · Enter …`
/// rendered as bold `Queue` + regular `d` (5 leaked bold cells).
#[test]
fn clears_leaked_modifiers_from_underpaint() {
let area = Rect::new(0, 0, 40, 1);
let mut buf = Buffer::empty(area);
// Simulate the phantom session-tip underpaint: 5 bold cells ("Tip: ").
buf.set_string(
0,
0,
"Tip: never gonna give you up",
Style::default().add_modifier(Modifier::BOLD),
);
// The send-now tip shape: dim text with a single bold key chord.
let dim = Style::default();
let bold = Style::default().add_modifier(Modifier::BOLD);
let line = Line::from(vec![
Span::styled("Queued · ", dim),
Span::styled("Enter", bold),
Span::styled(" to send now", dim),
]);
render_ephemeral_tip(area, &mut buf, &line);
assert_eq!(
row_text(&buf, area, 0).trim_end(),
"Queued · Enter to send now"
);
let bold_cols: Vec<u16> = (0..area.width)
.filter(|&x| {
buf.cell((x, 0))
.expect("cell in area")
.modifier
.contains(Modifier::BOLD)
})
.collect();
// "Queued · " occupies cols 0..9, "Enter" cols 9..14.
assert_eq!(
bold_cols,
(9..14).collect::<Vec<u16>>(),
"only the Enter chord may be bold — no leak from the underpaint"
);
}
}