Skip to content

Add Kimi CLI driver - #113

Open
simone-stacks wants to merge 10 commits into
protocol-security:masterfrom
simone-stacks:feat/kimi-cli-driver
Open

Add Kimi CLI driver#113
simone-stacks wants to merge 10 commits into
protocol-security:masterfrom
simone-stacks:feat/kimi-cli-driver

Conversation

@simone-stacks

Copy link
Copy Markdown
Contributor

Summary

  • Add a kimi-cli driver so swarms can run Kimi Code CLI alongside the existing drivers.
  • Install Kimi CLI in the agent image with a kimi_cli_version pin.
  • Wire the driver through launch, dashboard, docs, and tests.
  • Make upstream cloning more reliable with a shared retry helper.

Changes

  • lib/drivers/kimi-cli.sh: new driver implementing the swarm interface.
  • Dockerfile + launch.sh: install Kimi CLI and expose kimi_cli_version.
  • dashboard.sh, USAGE.md, README.md, CHANGELOG.md: surface the new driver.
  • tests/: add driver/config/dashboard/harness/launch coverage and Kimi fixture swarmfiles.
  • lib/upstream-clone.sh, lib/harness.sh, lib/interactive.sh: retry upstream clones on transient failures.
  • tests/test_upstream_clone.sh: unit tests for the clone helper.

Self-review checklist

  • This PR addresses a single concern (why?). If it covers multiple independent changes, I've split them into separate PRs.
  • The new driver is covered by unit tests.
  • The clone helper is covered by unit tests.
  • shellcheck -s bash passes on all modified .sh files.
  • New source lines stay within the 79-character project limit.

Test plan

  • shellcheck -s bash lib/upstream-clone.sh lib/harness.sh lib/interactive.sh lib/drivers/kimi-cli.sh tests/test_upstream_clone.sh
  • tests/test_upstream_clone.sh
  • tests/test_harness.sh
  • tests/test_drivers.sh
  • ./tests/test.sh --unit (note: test_harvest.sh and test_manual_interactive_e2e.sh have pre-existing issues on this branch)

@moodmosaic

Copy link
Copy Markdown
Member

@simone-stacks, thank you for the PR! Planning to test (and potentially merge soon). 🚀

@simone-stacks simone-stacks mentioned this pull request Aug 5, 2026
10 tasks
@simone-stacks
simone-stacks marked this pull request as draft August 24, 2026 10:48
@simone-stacks
simone-stacks marked this pull request as ready for review September 1, 2026 16:14
@radubahmata

Copy link
Copy Markdown
Contributor

@simone-stacks Hello from the other side! 👋 I'm going to start looking into your PRs. First thing I noticed is a flaky test (unrelated to this PR) that we're going to fix in a separate PR. Next I'll be running some local testing and eyeball your changes. I'll also spin up some review agents to make sure we're not missing anything.

@radubahmata radubahmata left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huge work! Some comments:

Comment thread lib/drivers/kimi-cli.sh
Comment on lines +203 to +215
agent_is_retriable() {
local logfile="$1"
local _rate='429\|rate.limit\|too many requests\|quota\|usage.limit\|hit your.*limit'
local _transient='connection reset\|connection closed\|connection refused\|gateway timeout\|bad gateway\|service unavailable\|\b50[234]\b\|timed out\|temporarily unavailable\|at capacity\|overloaded'
for f in "$logfile" "${logfile}.err"; do
[ -f "$f" ] || continue
grep -qi "$_rate" "$f" 2>/dev/null \
&& echo "rate_limited" && return
grep -qi "$_transient" "$f" 2>/dev/null \
&& echo "transient" && return
done
return 0
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The classifier misses retriable errors such as provider.connection_error and HTTP 408/409/500. After the harness' initial generic zero-token retry, a repeated connection error is treated as fatal.

Kimi 0.40.1 also treats connection errors and HTTP 408, 409, and 500 as retriable. The Kimi driver does not recognize those structured errors: https://github.com/MoonshotAI/kimi-code/blob/a7087694bb9dcc83c60c01fe51eb8c250d4656af/packages/agent-core-v2/src/kosong/contract/errors.ts#L234-L250

The fix would be to recognize Kimi's structured connection error and supported HTTP statuses.

Can you please also add some regression tests for provider.connection_error and HTTP 408, 409, and 500 in the existing Kimi retry-classification tests?

Comment thread tests/test_drivers.sh
EOF
RETRY_OUT=$(agent_is_retriable "$TMPDIR/kimi-503.jsonl" 1)
assert_not_empty "kimi 503 is retriable" "$RETRY_OUT"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be good enough as regression tests wrt the prev comment. Ran the suite locally and it fails. Let's do a TDD approach: please accept the suggestion so we can see the CI red, then turn green as soon as fix is pushed:

Suggested change
: > "$TMPDIR/kimi-connection.jsonl"
cat > "$TMPDIR/kimi-connection.jsonl.err" <<'EOF'
error: failed to run prompt: provider.connection_error: network error
EOF
RETRY_OUT=$(agent_is_retriable "$TMPDIR/kimi-connection.jsonl" 1)
assert_eq "kimi connection error is transient" "transient" "$RETRY_OUT"
for status in 408 409 500; do
printf '{"role":"meta","type":"turn.step.retrying",' > "$TMPDIR/kimi-${status}.jsonl"
printf '"status_code":%s}\n' "$status" >> "$TMPDIR/kimi-${status}.jsonl"
RETRY_OUT=$(agent_is_retriable "$TMPDIR/kimi-${status}.jsonl" 1)
assert_eq "kimi ${status} is transient" "transient" "$RETRY_OUT"
done

Comment thread USAGE.md
Comment on lines 642 to 644
Groups with `api_key` or `auth_token` ignore the `auth`
field; their custom credential is always used. When neither
is set, `auth` determines which host credential to inject.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed that the Kimi driver's pattern matching found here contradicts with this statement. Thought to add the comment there, but after further digging I realized that this holds only for Claude Code, while all remaining drivers clear the API key for auth: oauth/chatgpt. It's a nit, but since this is directly agent-facing and may lead to misleading swarmfiles I think we should fix/drop it.

Comment thread lib/drivers/kimi-cli.sh
Comment on lines +131 to +139
agent_extract_stats() {
local logfile="$1"
local turns
turns=$(grep -c '"role"[[:space:]]*:[[:space:]]*"assistant"' \
"$logfile" 2>/dev/null || true)
turns="${turns:-0}"
printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s" \
"0" "0" "0" "0" "0" "0" "0" "$turns"
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kimi's stream-json output does not include usage, but its LLM requester records provider-reported usage as usage.record entries. You can check this session fixture, it shows these entries serialized in agents/*/wire.jsonl with input, output, cache-read, and cache-creation counts. This function ignores those records and always returns zero; the harness derives pricing from those fields, so every Kimi run remains 0 regardless of actual usage.

Please resolve the emitted session ID and aggregate its usage.record entries across every agent wire file before returning stats. We should also add regression fixtures covering this.

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.

3 participants