MoonshotAI / MoonshotAI/kimi-code

kimi web: terminal creation fails in the packaged binary (node-pty native assets not bundled; deeper hang after fixing)

Open
#3,326 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
7.5k
Forks
1.2k
Avg merge
11h 53m
Merged PRs (30d)
350

Description

What happens

With the packaged single-file CLI (install.ps1 / SEA build), start kimi web and create a terminal from the web UI (or via the API):

POST /api/v1/sessions/{session_id}/terminals
{"runtime_id":"local","shell":"cmd.exe","cols":80,"rows":24}

The request fails with code 50001:

Failed to load native module: conpty.node, checked: build/Release, build/Debug, prebuilds/win32-x64:
Error [ERR_UNKNOWN_BUILTIN_MODULE]: No such built-in module: ./prebuilds/win32-x64//conpty.node

Web terminals are therefore completely unusable in the packaged binary (dev mode via pnpm dev:cli is unaffected). Confirmed on 0.39.0, Windows 11 x64.

Root cause (layer 1)

  • HostTerminalService.spawn (agent-core-v2/.../hostTerminalService.ts) lazily runs await import('node-pty').
  • node-pty's JS is bundled into the SEA blob, but its native prebuilds (prebuilds/<target>/*.node, plus winpty-agent.exe / conpty/OpenConsole.exe / conpty.dll on Windows, spawn-helper on darwin) are not registered in apps/kimi-code/scripts/native/native-deps.mjs (only clipboard and pi-tui are), so they never ship as native assets.
  • Additionally, inside the SEA main script the bundled require(dir+"/"+name+".node") in node-pty/lib/utils.js runs as the builtin-only require variant and throws ERR_UNKNOWN_BUILTIN_MODULE before Module._load can intercept it — so apps/kimi-code/src/native/module-hook.ts (which currently only redirects pi-tui patterns) never sees the request.

What we tried (layer 1 fixed, layer 2 found)

We implemented the pi-tui-style fix locally:

  1. Registered node-pty in native-deps.mjs with per-target prebuild files (plus 0o755 for darwin spawn-helper).
  2. Extended module-hook.ts with a redirect for node-pty prebuilds/<target>/ requires to the extracted cache copy.
  3. Added a small bundler plugin that rewrites the exact require(dir + "/" + name + ".node") call site in node-pty/lib/utils.js to createRequire(pathToFileURL(__filename).href)(...), failing the build loudly if a node-pty upgrade moves the call site.

Result: the 50001 error is gone — conpty.node now loads from the extracted native-asset cache, and test:native:smoke passes. But terminal creation then hangs the entire server event loop (no error response; the process stays alive but stops answering requests).

Current leading hypothesis: node-pty spawns new Worker(__dirname/worker/conoutSocketWorker.js) in its Windows conout connection, and that worker file does not exist inside the SEA bundle — the repo already solves the same problem for its own workers (minidb/search workers are extracted to disk as runtime files). The conout worker likely needs the same treatment (extract + rewrite the script path at bundle time), though a blocking fs.openSync on the conin pipe hasn't been ruled out.

Control experiment: the extracted node-pty (same cache copy) spawns cmd.exe successfully under plain node, so the .node binaries and sidecars themselves are fine — the hang is specific to the SEA process context.

We're happy to PR the layer-1 fix and/or continue with the worker extraction under maintainer guidance — whichever you prefer.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with apps/kimi-code/scripts/native/native-deps.mjs and apps/kimi-code/src/native/module-hook.ts, then inspect node-pty/lib/utils.js and its worker path. Run test:native:smoke and reproduce terminal creation in the packaged SEA binary, comparing it with plain node. Done means packaged Windows terminal creation returns successfully without hanging the server.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
backend, build-system, cli
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.