Skip to content

fix(runtime): stage oversize kimi prompts to a temp file to clear ARG_MAX#727

Merged
jerryfane merged 2 commits into
mainfrom
fix/723-kimi-argmax
Jul 7, 2026
Merged

fix(runtime): stage oversize kimi prompts to a temp file to clear ARG_MAX#727
jerryfane merged 2 commits into
mainfrom
fix/723-kimi-argmax

Conversation

@jerryfane

Copy link
Copy Markdown
Owner

What

The kimi runtime adapter passed the whole rendered prompt as a single -p argv argument. Any prompt above the Linux per-argument limit MAX_ARG_STRLEN (~128 KiB) fails fork/exec with E2BIG — argument list too long. This killed live skillopt synth judge calls, where context + question + rubric + two embedded agent answers overflowed a single argument (#723).

Why

Kimi Code exposes no stdin or prompt-file channel. Probed against the box's kimi-code 0.19.x:

  • -p, --prompt <prompt> is the only prompt input.
  • -p - is taken literally (the model receives a bare -), not as a stdin sentinel.
  • There is no --prompt-file / @file flag (a bare path is just treated as text the agent may or may not read).

So kimi genuinely cannot accept an oversize prompt through argv, and cannot fall back to stdin the way claude/codex can.

How

internal/runtime/kimi.go:

  • New kimiPromptDelivery(prompt)(promptArg, cleanup, err). Below a 100 KiB safety threshold (well under the hard 128 KiB limit) it returns the prompt verbatim and a no-op cleanup — byte-identical to the previous behavior for all normal prompts. At/above the threshold it stages the prompt to a temp file (system temp, not the job worktree, so it never pollutes or gets committed by an implement job) and returns a short, argv-safe wrapper instruction telling the agent to read that file as its full task. Callers defer cleanup().
  • Wired into KimiAdapter.Start, KimiAdapter.Deliver, and the legacy KimiCLIAdapter.Start/Deliver (they share the exposure; --print shape preserved).

internal/runtime/adapter.go:

  • Audited claude + codex. Both also pass the prompt as a trailing argv arg, but their CLIs read the prompt from stdin (codex exec -/omitted; claude -p stdin), so they have a native escape hatch. The CLIs differ from kimi, so per the issue this PR fixes kimi only and documents the argv exposure + stdin hatch in adapter comments; routing claude/codex through stdin is deferred to a follow-up.

website/docs/reference/runtime-adapters.md: documented the oversize-prompt (>=100 KiB) staging behavior for the Kimi adapter.

How tested

Toolchain: export PATH=/root/.local/toolchains/go1.26.4/bin:$PATH (go1.26.4).

  • go build ./... → clean (exit 0).
  • go vet ./... → clean (exit 0).
  • go test -count=1 ./internal/runtime/...ok (exit 0).
  • go test -race -count=1 ./internal/runtime/...ok (exit 0).
  • cd website && npm ci && npm run build[SUCCESS] Generated static files in "build". (exit 0).

New unit + no-LLM E2E tests in internal/runtime/kimi_prompt_test.go (fake runner that reads the staged temp file during Run, before deferred cleanup):

  • short prompt = passed verbatim as -p value, no temp file;
  • boundary: threshold-1 bytes = verbatim argv; exactly threshold bytes = staged temp file with content intact + argv-safe wrapper;
  • long prompt via Deliver and Start = temp file staged, content intact, raw prompt never appears in argv, temp file removed after return;
  • legacy kimi-cli shares the protection and keeps --print.

Real-binary verification against the live kimi CLI (read-only):

  • 162 KiB single-arg prompt reproduces fork/exec ... argument list too long.
  • 369-byte temp-file wrapper launches cleanly; kimi reads the staged file via its Read tool and returns the exact expected token.

Known limitation (noted honestly): kimi's Read tool truncates individual very long lines (>~a few KB on one line). Real prompts (PR context, diffs, embedded answers) are multi-line, so this doesn't affect normal use; it only showed up in a synthetic single-giant-line padding test. The fix is a strict improvement over the previous hard crash.

Note: website/static/llms-full.txt regen was intentionally omitted — regenerating it sweeps in large pre-existing unrelated drift on main (Chat feature sections, etc.); the human-authored source doc is updated.

Closes #723.

🤖 Generated with Claude Code

jerryfane and others added 2 commits July 7, 2026 18:22
…_MAX

The kimi adapter passes the whole rendered prompt as a single `-p` argv
argument. Any prompt above the kernel's per-argument MAX_ARG_STRLEN
(~128 KiB) fails fork/exec with E2BIG ("argument list too long"), which
killed live synth-judge calls where context + question + rubric + two
embedded agent answers overflowed one argument (#723).

Kimi Code exposes no stdin or prompt-file channel (`-p, --prompt <prompt>`
is the only prompt input, and `-p -` is taken literally, not as a stdin
sentinel — probed against kimi-code 0.19.x). So when a prompt reaches a
100 KiB safety threshold, Gitmoot now stages it to a temp file and passes a
short, argv-safe instruction telling the agent to read that file as its full
task. Normal-size prompts are passed verbatim, byte-identical to before.
Both the `kimi` and legacy `kimi-cli` runtimes share the protection, in
Start and Deliver.

The claude and codex adapters expose the prompt as a trailing argv arg too,
but their CLIs can read the prompt from stdin (codex: `exec -`/omitted;
claude: `-p` stdin), so they have a native escape hatch — documented in
adapter comments; routing them through stdin is deferred to a follow-up.

Verified end-to-end against the real kimi binary: a 162 KiB single-arg
prompt reproduces "argument list too long", and the 369-byte temp-file
wrapper launches cleanly, has the agent read the staged file, and returns
the exact expected token.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Grant kimi the staged prompt directory via --add-dir so its
workspace-scoped file-read tool can actually open an oversize prompt.

The oversize-prompt path staged the real prompt to a system-temp file
(os.CreateTemp("", ...)) outside any workspace and handed kimi only a
wrapper telling it to read that path, but never granted kimi access to
the dir. kimi-code's file-read tool is scoped to the session workspace
directories, so the read would be denied and the real prompt silently
lost (E2BIG avoided but no task delivered).

Fix: stage the prompt into a dedicated temp DIRECTORY (os.MkdirTemp) and
return a `--add-dir <dir>` grant (a real kimi-code 0.19.x flag) threaded
into the argv of both the kimi and legacy kimi-cli adapters, Start and
Deliver. Cleanup RemoveAll's the whole dir. Normal-size prompts stay
byte-identical (verbatim -p, no extra args).

Tests: kimiPromptDelivery boundary tests now assert the --add-dir grant
names the staged dir; the no-LLM Deliver/Start/CLI E2E tests assert the
staged dir appears in argv as --add-dir and matches the prompt file's
parent. Docs updated to describe the workspace grant.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jerryfane jerryfane merged commit 908387c into main Jul 7, 2026
1 check passed
@jerryfane jerryfane deleted the fix/723-kimi-argmax branch July 7, 2026 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

kimi adapter: prompt passed as argv blows ARG_MAX on long prompts (fork/exec: argument list too long)

1 participant