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).
135 lines
5.5 KiB
JavaScript
135 lines
5.5 KiB
JavaScript
#!/usr/bin/env node
|
||
// Assemble the six per-platform npm packages prior to `npm publish`.
|
||
//
|
||
// For each supported (platform, arch) target this:
|
||
// 1. Brotli-compresses the built binary into `../grok-<platform>/bin/<bin>.br`
|
||
// 2. Stamps the sub-package's version to match the meta package
|
||
//
|
||
// Each per-platform package is its own npm publish target. The meta package
|
||
// (`@xai-official/grok`) lists all six as `optionalDependencies` pinned to
|
||
// the same version; npm installs only the one matching the host's
|
||
// `os` + `cpu` filters.
|
||
//
|
||
// Why brotli? npm's tarball ceiling is ~200 MB and the raw grok binary is
|
||
// 100–150 MB per platform. Brotli at max quality cuts that to 30–40 MB,
|
||
// leaves plenty of headroom for binary growth, and is decoded by Node's
|
||
// built-in zlib.brotliDecompressSync (no native deps required).
|
||
//
|
||
// Source paths come from environment variables (set in CI) and fall back to
|
||
// the default cargo target dirs for local testing.
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const { promisify } = require('util');
|
||
const zlib = require('zlib');
|
||
|
||
const brotliCompress = promisify(zlib.brotliCompress);
|
||
|
||
const xaiRoot = process.env.XAI_ROOT || path.resolve(__dirname, '..', '..', '..', '..', '..');
|
||
const npmRoot = path.resolve(__dirname, '..', '..');
|
||
|
||
const NOTICES_SOURCE = path.resolve(
|
||
npmRoot, '..', '..', 'kigi-tools', 'THIRD_PARTY_NOTICES.md');
|
||
const NOTICES_NAME = 'THIRD_PARTY_NOTICES.md';
|
||
|
||
const META_PKG_JSON = path.resolve(__dirname, '..', 'package.json');
|
||
const meta = JSON.parse(fs.readFileSync(META_PKG_JSON, 'utf8'));
|
||
const VERSION = meta.version;
|
||
|
||
function ensureDir(p) { fs.mkdirSync(path.dirname(p), { recursive: true }); }
|
||
|
||
async function packPlatform({ platform, arch, envVar, defaultSource, binName }) {
|
||
const pkgDir = path.join(npmRoot, `grok-${platform}-${arch}`);
|
||
const pkgJsonPath = path.join(pkgDir, 'package.json');
|
||
|
||
if (!fs.existsSync(pkgJsonPath)) {
|
||
console.error(`[assemble] Missing per-platform package at ${pkgDir}`);
|
||
return false;
|
||
}
|
||
|
||
const source = process.env[envVar] || defaultSource;
|
||
if (!fs.existsSync(source)) {
|
||
console.error(`[assemble] Missing binary for ${platform}-${arch}: ${source}`);
|
||
console.error(` Set ${envVar} or build to the default location.`);
|
||
return false;
|
||
}
|
||
|
||
// Stamp the sub-package's version to match the meta package.
|
||
const subPkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
|
||
subPkg.version = VERSION;
|
||
fs.writeFileSync(pkgJsonPath, JSON.stringify(subPkg, null, 4) + '\n');
|
||
|
||
if (!fs.existsSync(NOTICES_SOURCE)) {
|
||
console.error(`[assemble] Missing third-party notices file: ${NOTICES_SOURCE}`);
|
||
return false;
|
||
}
|
||
fs.copyFileSync(NOTICES_SOURCE, path.join(pkgDir, NOTICES_NAME));
|
||
|
||
// Brotli-compress into the sub-package's bin/.
|
||
const outBr = path.join(pkgDir, 'bin', `${binName}.br`);
|
||
ensureDir(outBr);
|
||
const raw = fs.readFileSync(source);
|
||
const compressed = await brotliCompress(raw, {
|
||
params: { [zlib.constants.BROTLI_PARAM_QUALITY]: zlib.constants.BROTLI_MAX_QUALITY },
|
||
});
|
||
fs.writeFileSync(outBr, compressed);
|
||
console.log(
|
||
`[assemble] grok-${platform}-${arch}@${VERSION}: ` +
|
||
`${(raw.length / 1048576).toFixed(1)} MB -> ${(compressed.length / 1048576).toFixed(1)} MB ` +
|
||
`(${path.relative(npmRoot, outBr)})`
|
||
);
|
||
return true;
|
||
}
|
||
|
||
async function main() {
|
||
const targets = [
|
||
{
|
||
platform: 'darwin', arch: 'arm64', binName: 'grok',
|
||
envVar: 'KIGI_DARWIN_ARM64',
|
||
defaultSource: path.join(xaiRoot, 'target', 'release', 'kigi-tui'),
|
||
},
|
||
{
|
||
platform: 'darwin', arch: 'x64', binName: 'grok',
|
||
envVar: 'KIGI_DARWIN_X64',
|
||
defaultSource: path.join(xaiRoot, 'target', 'x86_64-apple-darwin', 'release', 'kigi-tui'),
|
||
},
|
||
{
|
||
platform: 'linux', arch: 'x64', binName: 'grok',
|
||
envVar: 'KIGI_LINUX_X64',
|
||
defaultSource: path.join(xaiRoot, 'target',
|
||
'explorer_cross_x86_64-unknown-linux-gnu',
|
||
'x86_64-unknown-linux-gnu', 'release', 'kigi-tui'),
|
||
},
|
||
{
|
||
platform: 'linux', arch: 'arm64', binName: 'grok',
|
||
envVar: 'KIGI_LINUX_ARM64',
|
||
defaultSource: path.join(xaiRoot, 'target',
|
||
'explorer_cross_aarch64-unknown-linux-gnu',
|
||
'aarch64-unknown-linux-gnu', 'release', 'kigi-tui'),
|
||
},
|
||
{
|
||
platform: 'win32', arch: 'x64', binName: 'grok.exe',
|
||
envVar: 'KIGI_WIN32_X64',
|
||
defaultSource: path.join(xaiRoot, 'target', 'x86_64-pc-windows-msvc', 'release', 'kigi-tui.exe'),
|
||
},
|
||
{
|
||
platform: 'win32', arch: 'arm64', binName: 'grok.exe',
|
||
envVar: 'KIGI_WIN32_ARM64',
|
||
defaultSource: path.join(xaiRoot, 'target', 'aarch64-pc-windows-msvc', 'release', 'kigi-tui.exe'),
|
||
},
|
||
];
|
||
|
||
// Compress in parallel — brotliCompress runs on the libuv thread pool so
|
||
// calls genuinely overlap (set UV_THREADPOOL_SIZE>=6 in CI for full
|
||
// parallelism; Node's default pool size is 4).
|
||
const results = await Promise.all(targets.map(packPlatform));
|
||
const failed = results.filter(r => !r).length;
|
||
if (failed > 0) {
|
||
console.error(`[assemble] ${failed} target(s) failed.`);
|
||
process.exit(1);
|
||
}
|
||
|
||
console.log(`[assemble] All 6 per-platform packages assembled at version ${VERSION}.`);
|
||
}
|
||
|
||
main().catch((err) => { console.error(err); process.exit(1); });
|