Skip to content

fix(integrations): map Kimi Code JSON dispatch to --output-format stream-json - #5031

Open
RaycarlLei wants to merge 1 commit into
github:mainfrom
RaycarlLei:fix/kimi-dispatch-output-format
Open

RaycarlLei wants to merge 1 commit into
github:mainfrom
RaycarlLei:fix/kimi-dispatch-output-format

Conversation

@RaycarlLei

Copy link
Copy Markdown

Description

KimiIntegration does not override build_exec_args(), so it inherits SkillsIntegration.build_exec_args() (base.py#L1708-L1727), which appends --output-format json when output_json is true.

Kimi Code CLI only accepts text and stream-json for that option. It is declared with Commander .choices(['text', 'stream-json']) (apps/kimi-code/src/cli/commands.ts#L70-L75) and documented in docs/en/reference/kimi-command.md#L22. 472192c is the @moonshot-ai/kimi-code@2.2.0 tag, the current npm latest. Commander rejects json while parsing options, before any prompt runs, so this reproduces without a Kimi account. With KIMI_CODE_HOME pointing at an empty directory (not logged in):

$ kimi --version
2.2.0
$ kimi -p x --output-format json
error: option '--output-format <format>' argument 'json' is invalid. Allowed choices are text, stream-json.
$ echo $?
1
$ kimi -p x --output-format stream-json
{"role":"meta","type":"system.version","version":"2.2.0"}
error: failed to run prompt: No model configured. Run `kimi` and use /login to sign in, then retry; or set default_model in config.toml.
See log: $KIMI_CODE_HOME/logs/kimi-code.log

The stream-json run gets past option parsing and only stops because that empty home has no model configured.

The same failure through Spec Kit on main (f68ffca), with kimi 2.2.0 on PATH:

$ .venv/bin/python -c "from specify_cli.integrations.kimi import KimiIntegration as K; r = K().dispatch_command('speckit.plan', 'x', stream=False); print(r['exit_code'], r['stderr'].strip())"
1 error: option '--output-format <format>' argument 'json' is invalid. Allowed choices are text, stream-json.

Reachability. The built-in workflow steps do not hit this. The command step either streams, where output_json is left as None and resolves to not stream, i.e. False (base.py#L463-L464), or captures with an explicit output_json=False (step/command/__init__.py#L313-L319). The prompt step passes output_json=False (step/prompt/__init__.py#L248-L253). It is reached through the public dispatch_command(..., stream=False) when output_json is left unset (it then resolves to True), through direct build_exec_args() calls (default output_json=True), and by extensions or other callers of those APIs.

Fix. Override build_exec_args() in KimiIntegration so structured output requests --output-format stream-json (JSONL events), the same approach Amp took with --stream-json in #4581. The rest matches the base implementation: the requires_cli guard, -p <prompt>, SPECKIT_INTEGRATION_KIMI_EXTRA_ARGS before --model, and --model, which Kimi accepts (-m, --model <model>, commands.ts#L58-L63). The override sits below post_process_skill_content(), clear of the build_command_invocation() removal in #4983.

Part of #2416, which lists Kimi among the SkillsIntegration CLIs that inherit the -p argv without verification.

Testing

  • Tested locally with uv run specify --help

  • Ran existing tests with uv sync && uv run pytest

  • Tested with a sample project (if applicable): see the first bullet below

  • Sample project: specify init --integration kimi, then dispatch_command('speckit.plan', ..., stream=False) against kimi 2.2.0, with KIMI_CODE_HOME configured for a local OpenAI-compatible stub model because no Kimi account was available. On main it exits 1 with the Commander error above. On this branch it exits 0 and stdout holds three JSONL events (system.version, the assistant message, session.resume_hint).

  • tests/integrations/test_integration_kimi.py gets four argv tests: text mode, stream-json, --model, and SPECKIT_INTEGRATION_KIMI_EXTRA_ARGS. Run against main, the stream-json and extra-args cases fail with 'json' != 'stream-json'. All four pass on this branch.

  • .venv/bin/python -m pytest tests/integrations tests/workflows tests/test_agent_config_consistency.py -q: 3551 passed, 8 skipped.

  • uvx ruff@0.15.0 check src tests: all checks passed.

  • Full suite, .venv/bin/python -m pytest tests -q (macOS, Python 3.14.3): 12417 passed, 376 skipped, 24 failed. All 24 are in 9 files this PR does not touch, and running those files on unmodified main on the same machine fails the same 24 test IDs. 13 come from the checkout and temp directory sitting under a path with a space: path assertions in test_init_dir.py, test_timestamp_branches.py and tests/specify_cli/workflows/step/test_command_add.py, plus the #!<sys.executable> shebang of the fake curl in test_workflow_step_submission.py. The other 11 are composed-template cases in test_*_python_parity.py, whose bash variant runs python3 from PATH, and that interpreter has no PyYAML on this machine.

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (fill in the disclosure below)

AI disclosure: Claude Code opened this PR on behalf of @RaycarlLei. Claude Code (model: Claude Opus 5.5, reasoning effort xhigh, autonomous agent mode with tool approvals bypassed) reproduced the bug against kimi 2.2.0, read the Kimi Code source for the allowed --output-format values, wrote the override and the four tests, ran the checks above, wrote this description, and pushed the branch. Read-only Claude Code subagents on the same model and effort cross-checked the description's claims and the diff before posting. @RaycarlLei reviewed the diff and a draft of this description and approved posting, but did not re-run the tests or edit the text. The commit carries Assisted-by: Claude Code (model: Claude Opus 5.5, autonomous).

🤖 Generated with Claude Code

…eam-json

KimiIntegration inherited SkillsIntegration.build_exec_args(), which
appends --output-format json when output_json is true. Kimi Code CLI
restricts --output-format to text and stream-json, so its option parser
rejects the value and kimi exits 1 before the prompt runs. This is
reachable through dispatch_command(stream=False) when output_json is
left unset (it then resolves to True), and through direct
build_exec_args() calls.

Override build_exec_args() to request stream-json instead, keeping the
base requires_cli guard and argument order (EXTRA_ARGS before --model).

Assisted-by: Claude Code (model: Claude Opus 5.5, autonomous)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@RaycarlLei
RaycarlLei requested a review from mnriem as a code owner October 19, 2026 23:53
@mnriem mnriem added the triage-must-have Verdict: high-value, important work for Spec Kit — do first label Oct 20, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage-must-have Verdict: high-value, important work for Spec Kit — do first

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants