mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-07-30 11:35:02 +00:00
* feat(tree-sitter-bash): scaffold pure-TypeScript bash parser package
Add packages/tree-sitter-bash with the SyntaxNode tree model (UTF-16
code-unit offsets, tree-sitter-bash named-node type names), a parse
budget (deadline + node cap) with an aborted ParseResult variant, and
a placeholder parse() to be replaced by the real lexer/parser.
* feat(tree-sitter-bash): add lexer and core recursive-descent parser
Cover the permission-analysis grammar subset: lists, pipelines,
commands, words, quotes, expansions, command/process substitution,
subshells, the full redirect operator set, heredocs and comments,
with tree-sitter-bash named-node type names. Long scan loops check
the parse deadline via budget.progress() so large literals cannot
exhaust the node cap; parse depth is bounded on all recursion
chains.
* feat(tree-sitter-bash): support the full bash grammar
Add compound commands (if/while/until/for/c-style-for/select/case/
function/compound/do_group), test commands with reference-exact
extglob/regex right-hand-side rules, a Pratt expression engine for
arithmetic expansion shared across arith/c-for/test modes, arrays
and subscripts, declaration/unset commands, ansi-c/translated
strings and brace expressions. Reserved words are recognized only
in statement position. Case-aware balanced scanning keeps command
substitutions intact around case items, expression leftovers are
kept as ERROR nodes instead of dropped, and recursion depth is
bounded per chain (substitution 150, parse 500, lexer scan 1024).
* test(tree-sitter-bash): add differential fixtures, corpus, fuzz and perf suites
Turn the ad-hoc wasm comparison work into permanent infrastructure:
a differential helper pinning reference-equivalent and
known-difference samples against the real tree-sitter-bash wasm
(478 match / 79 known-diff fixtures plus the official v0.25.0
corpus), a three-way consistency check between fixtures, the
known-difference registry and the README, deterministic seeded
fuzz with tree-integrity assertions, and performance smoke tests.
Converges 15 further divergence groups found by systematic probing
and documents the rest; the full suite is 853 tests in ~4s.
* feat(agent-core-v2): add App-scope bashParser service
Wrap the pure @moonshot-ai/tree-sitter-bash package as
IBashParserService (L1, no dependencies): parse(source, options)
returns a wire-safe BashParseResult whose nodes drop the cyclic
parent link so trees can cross the RPC boundary. Budget exhaustion
surfaces as { ok: false, reason: 'aborted' }, malformed input as
hasError — never a throw.
* chore: add changeset for the bash parser service
* chore: update pnpmDeps hash after adding tree-sitter-bash package
* fix(agent-core-v2): register bashParser service with ScopeActivation
The registration was written against the removed InstantiationType API
(#/_base/di/extensions); switch to ScopeActivation.OnDemand from
#/_base/di/scope so the package typechecks and the service registers.
* feat(kimi-inspect): add Bash Parser view
Add a fourth icon-rail tab that exercises the App-scope bash parser
service over the debug RPC surface: a source textarea with a parse
budget (timeoutMs / maxNodes), a dropdown of curated examples adapted
from the tree-sitter-bash differential fixtures, and an expandable
syntax tree with per-node type, UTF-16 range and leaf text, plus
hasError / aborted / node-count badges.
* fix(agent-core-v2): snapshot bash syntax trees iteratively
A long left-associative chain (e.g. an arithmetic expression with a
few thousand operands) parses into a tree thousands of levels deep
while still within budget; the recursive DTO conversion then overflowed
the JS call stack and made parse throw RangeError, breaking the
never-throws contract. Convert the tree with an explicit stack, the
same approach as the parser's own materialize.
* feat(kimi-inspect): add a deep-arithmetic example to the Bash Parser view
A thousand-operand left-associative chain fills the textarea with a
thousand-level binary_expression tree — the shape that once overflowed
the DTO conversion. Deeper chains still parse in-process but cannot
cross the JSON RPC transport (V8 call-stack limit in serialization),
so the example stays within the wire limit.
* chore: update pnpmDeps hash for the rebased lockfile
The rebase onto main merged pnpm-lock.yaml, invalidating the recorded
fetchPnpmDeps hash; use the hash CI computed for the merged lockfile.
265 lines
8.5 KiB
Nix
265 lines
8.5 KiB
Nix
{
|
|
description = "Kimi Code CLI";
|
|
|
|
inputs = {
|
|
# Pinned to the 25.11 release channel because nixpkgs-unstable currently
|
|
# ships nodejs_24 = 24.14.1, which trips the >= 24.15.0 floor that the
|
|
# native SEA build enforces (see apps/kimi-code/scripts/native/build.mjs).
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
|
|
};
|
|
|
|
outputs =
|
|
{ self, nixpkgs }:
|
|
let
|
|
lib = nixpkgs.lib;
|
|
|
|
systems = [
|
|
"x86_64-linux"
|
|
"aarch64-linux"
|
|
"x86_64-darwin"
|
|
"aarch64-darwin"
|
|
];
|
|
|
|
forAllSystems =
|
|
f:
|
|
lib.genAttrs systems (
|
|
system:
|
|
f (import nixpkgs {
|
|
inherit system;
|
|
})
|
|
);
|
|
|
|
minNodeVersion = "24.15.0";
|
|
|
|
# Hardcode to Node.js 24.x; fail the evaluation if the pinned nixpkgs
|
|
# does not offer a new enough 24.x.
|
|
nodejsFor =
|
|
pkgs:
|
|
let
|
|
node = pkgs.nodejs_24;
|
|
in
|
|
if lib.versionAtLeast node.version minNodeVersion then
|
|
node
|
|
else
|
|
throw ''
|
|
Kimi Code requires Node.js >= ${minNodeVersion},
|
|
but nixpkgs only offers ${node.version}.
|
|
Pin a newer nixpkgs revision or update minNodeVersion in flake.nix.
|
|
'';
|
|
|
|
pnpmFor =
|
|
pkgs:
|
|
pkgs.pnpm_10.override {
|
|
nodejs = nodejsFor pkgs;
|
|
};
|
|
|
|
# -------------------------------------------------------------------
|
|
# Workspace members (kept in sync with pnpm-workspace.yaml).
|
|
#
|
|
# HARD REQUIREMENT: whenever you add or remove a workspace package,
|
|
# you MUST update both lists below. Missing a path will break the Nix
|
|
# build (src fileset silently drops files); missing a name will break
|
|
# pnpmConfigHook (dependencies for that workspace won't be fetched).
|
|
# -------------------------------------------------------------------
|
|
workspacePaths = [
|
|
./packages/acp-adapter
|
|
./packages/agent-core
|
|
./packages/agent-core-v2
|
|
./packages/kap-server
|
|
./packages/kaos
|
|
./packages/klient
|
|
./packages/kosong
|
|
./packages/migration-legacy
|
|
./packages/minidb
|
|
./packages/node-sdk
|
|
./packages/oauth
|
|
./packages/pi-tui
|
|
./packages/protocol
|
|
./packages/telemetry
|
|
./packages/transcript
|
|
./packages/tree-sitter-bash
|
|
./apps/kimi-code
|
|
./apps/vscode
|
|
./apps/kimi-inspect
|
|
./apps/kimi-web
|
|
./apps/vis
|
|
./apps/vis/server
|
|
./apps/vis/web
|
|
./docs
|
|
];
|
|
|
|
workspaceNames = [
|
|
"@moonshot-ai/acp-adapter"
|
|
"@moonshot-ai/agent-core"
|
|
"@moonshot-ai/agent-core-v2"
|
|
"@moonshot-ai/kap-server"
|
|
"@moonshot-ai/kaos"
|
|
"@moonshot-ai/kosong"
|
|
"@moonshot-ai/migration-legacy"
|
|
"@moonshot-ai/minidb"
|
|
"@moonshot-ai/kimi-code-sdk"
|
|
"@moonshot-ai/kimi-code-oauth"
|
|
"@moonshot-ai/klient"
|
|
"@moonshot-ai/pi-tui"
|
|
"@moonshot-ai/protocol"
|
|
"@moonshot-ai/kimi-telemetry"
|
|
"@moonshot-ai/transcript"
|
|
"@moonshot-ai/tree-sitter-bash"
|
|
"@moonshot-ai/kimi-code"
|
|
"kimi-code"
|
|
"@moonshot-ai/kimi-inspect"
|
|
"@moonshot-ai/kimi-web"
|
|
"@moonshot-ai/vis"
|
|
"@moonshot-ai/vis-server"
|
|
"@moonshot-ai/vis-web"
|
|
"kimi-code-docs"
|
|
];
|
|
in
|
|
{
|
|
packages = forAllSystems (
|
|
pkgs:
|
|
let
|
|
nodejs = nodejsFor pkgs;
|
|
pnpm = pnpmFor pkgs;
|
|
appPackageJson = builtins.fromJSON (builtins.readFile ./apps/kimi-code/package.json);
|
|
nativeTarget =
|
|
if pkgs.stdenv.hostPlatform.isLinux && pkgs.stdenv.hostPlatform.isAarch64 then
|
|
"linux-arm64"
|
|
else if pkgs.stdenv.hostPlatform.isLinux then
|
|
"linux-x64"
|
|
else if pkgs.stdenv.hostPlatform.isDarwin && pkgs.stdenv.hostPlatform.isAarch64 then
|
|
"darwin-arm64"
|
|
else if pkgs.stdenv.hostPlatform.isDarwin then
|
|
"darwin-x64"
|
|
else
|
|
throw "Unsupported Kimi Code native target for ${pkgs.stdenv.hostPlatform.system}";
|
|
|
|
kimi-code = pkgs.stdenv.mkDerivation (finalAttrs: {
|
|
pname = "kimi-code";
|
|
version = appPackageJson.version;
|
|
|
|
src = lib.fileset.toSource {
|
|
root = ./.;
|
|
fileset = lib.fileset.unions (
|
|
[
|
|
./build
|
|
./.npmrc
|
|
./.nvmrc
|
|
./package.json
|
|
./pnpm-lock.yaml
|
|
./pnpm-workspace.yaml
|
|
./tsconfig.json
|
|
./vitest.config.ts
|
|
./LICENSE
|
|
]
|
|
++ workspacePaths
|
|
);
|
|
};
|
|
|
|
pnpmWorkspaces = [ "." ] ++ workspaceNames;
|
|
|
|
pnpmDeps = pkgs.fetchPnpmDeps {
|
|
inherit (finalAttrs) pname version src pnpmWorkspaces;
|
|
inherit pnpm;
|
|
fetcherVersion = 3;
|
|
hash = "sha256-bL1AaInlb8dE+ua7a6llvQWkibEwEzfI3oQW5IOpX6I=";
|
|
};
|
|
|
|
nativeBuildInputs = [
|
|
nodejs
|
|
pnpm
|
|
(pkgs.pnpmConfigHook.override { inherit pnpm; })
|
|
pkgs.makeWrapper
|
|
]
|
|
# The SEA inject step (postject) invalidates the macOS code
|
|
# signature on the copied Node executable; build.mjs then re-applies
|
|
# an ad-hoc signature via `codesign`. The Nix darwin sandbox does
|
|
# not expose /usr/bin/codesign, so we supply nixpkgs' ad-hoc-only
|
|
# replacement instead.
|
|
++ lib.optionals pkgs.stdenv.hostPlatform.isDarwin [
|
|
pkgs.darwin.sigtool
|
|
];
|
|
|
|
# The SEA binary is produced by `postject`-injecting a blob into a
|
|
# plain Node executable. Stripping rewrites section tables and can
|
|
# invalidate the injected blob's offsets, so leave the binary
|
|
# untouched after the build.
|
|
dontStrip = true;
|
|
|
|
buildPhase = ''
|
|
runHook preBuild
|
|
export KIMI_CODE_BUILD_TARGET=${nativeTarget}
|
|
${lib.optionalString pkgs.stdenv.hostPlatform.isDarwin ''
|
|
# pkgs.darwin.sigtool's codesign supports `--sign -` (ad-hoc)
|
|
# but not the inspection mode (`-dv`) that 05-verify.mjs runs
|
|
# afterwards. Disable the verify step for the Nix build; the
|
|
# release CI keeps it via the unmodified script.
|
|
substituteInPlace apps/kimi-code/scripts/native/build.mjs \
|
|
--replace-fail \
|
|
"await runVerifyStep({ requireGatekeeper: false });" \
|
|
"// runVerifyStep skipped in nix sandbox (sigtool lacks -dv)"
|
|
''}
|
|
# The SEA blob step (scripts/native/02-sea-blob.mjs) embeds the
|
|
# Kimi web assets from apps/kimi-code/dist-web and fails if that
|
|
# directory is missing. Build the web app and stage its assets
|
|
# before producing the native executable.
|
|
pnpm --filter=@moonshot-ai/kimi-web run build
|
|
node apps/kimi-code/scripts/copy-web-assets.mjs
|
|
pnpm --filter=@moonshot-ai/kimi-code run build:native:sea
|
|
runHook postBuild
|
|
'';
|
|
|
|
installPhase = ''
|
|
runHook preInstall
|
|
|
|
install -Dm755 \
|
|
"apps/kimi-code/dist-native/bin/${nativeTarget}/kimi" \
|
|
"$out/bin/kimi"
|
|
|
|
runHook postInstall
|
|
'';
|
|
|
|
postInstall = ''
|
|
wrapProgram $out/bin/kimi --prefix PATH : ${lib.makeBinPath [ pkgs.ripgrep pkgs.fd ]}
|
|
'';
|
|
|
|
meta = {
|
|
description = "Kimi Code CLI";
|
|
homepage = "https://github.com/MoonshotAI/kimi-code";
|
|
license = lib.licenses.mit;
|
|
mainProgram = "kimi";
|
|
platforms = systems;
|
|
};
|
|
});
|
|
in
|
|
{
|
|
inherit kimi-code;
|
|
default = kimi-code;
|
|
}
|
|
);
|
|
|
|
apps = forAllSystems (pkgs: {
|
|
kimi-code = {
|
|
type = "app";
|
|
program = "${self.packages.${pkgs.system}.kimi-code}/bin/kimi";
|
|
};
|
|
default = self.apps.${pkgs.system}.kimi-code;
|
|
});
|
|
|
|
devShells = forAllSystems (pkgs: {
|
|
default =
|
|
let
|
|
nodejs = nodejsFor pkgs;
|
|
pnpm = pnpmFor pkgs;
|
|
in
|
|
pkgs.mkShell {
|
|
packages = [
|
|
nodejs
|
|
pnpm
|
|
pkgs.ripgrep
|
|
pkgs.fd
|
|
];
|
|
};
|
|
});
|
|
};
|
|
}
|