feat(kimi): Kimi K3 provider on the official kimi-code CLI (#713)

* feat(kimi): Kimi K3 provider on the official kimi-code CLI (Wave 1)

ModelProvider.KIMI routes through KimiCliProvider driving Moonshot's kimi
CLI on a Kimi subscription (OAuth device-code, no metered key). One-shot
delivery roles only (V1), interactive ban wired in both guard lists.

Auth: one shared RW auth mount; containers symlink credentials/ and
oauth/ (the CLI's cross-process refresh-lock dir) into a container-local
KIMI_CODE_HOME so every container and the host redeem the SAME rotating
refresh chain - live-verified that per-copy chains cross-invalidate after
the reuse-grace window. No orchestrator refresh daemon; an expires_at
preflight exits 78.

Config renderer mirrors the login-managed provider/model blocks
field-for-field (live-captured; the model value is the CLI-side name,
never the raw API id), plus per-role deny rules and the bash-guard as a
PreToolUse hook via a wrapper script (an env key on a hooks entry makes
the CLI silently drop ALL hooks - live-verified). Usage capture sums
wire.jsonl usage.record 4-bucket events; sniff classifies rate-limit/auth
from structured error text only, mapped to the shared 75/78 park
contract. Image installs the CLI latest-at-build (no version pin, by
policy) with the resolved version stamped as provenance, binary split to
/usr/local away from mutable state.

Migrations 090 (enum) + 091 (provider seed); catalog, pricing, routing
mode, and orchestrator park/usage wiring mirror the codex integration.

* feat(kimi): surface sweep + fleet-wide pin drop (Wave 2)

Compose x3 gain the agent-kimi-image service and the orchestrator's
read-write ~/.kimi-code mount + kimi-usage dir; .env.example documents
the Kimi block. Panel mirrors ModelProvider.KIMI and adds the kimi
routing mode (catalog filter, mode button, mix-picker group, badge) with
tests; provider routes gain the kimi remediation entry. CLAUDE.md and
docs/map document the runtime. Per the no-pins policy, agent-grok/
gemini/codex Dockerfiles drop their version pins for latest-at-build
with resolved-version provenance stamps (grok resolves 0.2.112 vs the
old 0.2.56 pin - verified by real builds of all four images).

---------

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
Renzo F
2026-07-29 01:48:55 +02:00
committed by GitHub
co-authored by Renn F
parent eb470dfb33
commit 6374bbbed0
43 changed files with 3907 additions and 110 deletions
+36
View File
@@ -420,6 +420,21 @@ services:
depends_on:
- agent-base-image
# ==========================================================================
# Agent Kimi Image Builder (Moonshot AI Kimi K3 via the official kimi CLI).
# One-shot delivery roles only (V1) — no interactive prompter/secretary
# variant exists for Kimi yet, contrast the Grok images above.
# ==========================================================================
agent-kimi-image:
build:
context: .
dockerfile: docker/agent-kimi.Dockerfile
image: roboco-agent-kimi
entrypoint: ["/bin/sh", "-c", 'echo "Agent Kimi image built"']
restart: "no"
depends_on:
- agent-base-image
# ==========================================================================
# Sandbox PG Image Builder (kitchen-sink postgres for parameterized dev DBs)
# Only pulled by the provisioner when a venture requests pg extensions; bare
@@ -510,6 +525,14 @@ services:
# mounts <dir>/oauth_creds.json (read-only) into each Gemini agent. Run
# `gemini` interactively once on the host to produce it.
ROBOCO_HOST_GEMINI_DIR: ${ROBOCO_HOST_GEMINI_DIR:-/home/renzof/.gemini}
# Kimi subscription auth (host ~/.kimi-code) for Kimi-CLI agents — the
# orchestrator mounts <dir>/credentials/kimi-code.json into each Kimi
# agent. Run `kimi login` on the host. Read-WRITE (see the volumes
# mount below): unlike gemini's reusable refresh token, Kimi's refresh
# is rotation-with-short-reuse-grace, so every container shares this
# ONE host chain via a symlinked-in credentials/+oauth/ mount rather
# than a per-container copy (kimi follows codex's RW mount mode here).
ROBOCO_HOST_KIMI_DIR: ${ROBOCO_HOST_KIMI_DIR:-/home/renzof/.kimi-code}
ROBOCO_HOST_DATA_DIR: ${ROBOCO_HOST_DATA_DIR:-/volume1/roboco/data}
# Public base URL for commit-trailer links. Default 127.0.0.1 produces
# unusable links in commit message bodies; set to NAS LAN IP so
@@ -735,6 +758,17 @@ services:
# IN-PROCESS by each agent container's own CLI — never by the
# orchestrator — so no read-write access is needed here.
- ${ROBOCO_HOST_GEMINI_DIR:-/home/renzof/.gemini}:${ROBOCO_HOST_GEMINI_DIR:-/home/renzof/.gemini}:ro
# Kimi subscription auth — mount the host ~/.kimi-code at the SAME host
# path the orchestrator passes to each Kimi agent's `-v`, so the
# credentials/kimi-code.json exists() check passes here AND the agent
# bind resolves on the host. Read-WRITE (unlike gemini's RO mount
# above): Moonshot's refresh token is rotation-with-short-reuse-grace,
# not truly reusable, so every container symlinks credentials/+oauth/
# from this ONE shared chain instead of refreshing a private copy —
# the CLI's own cross-process lock (oauth/kimi-code.lock) serializes
# redemptions. No orchestrator refresh daemon (the CLI refreshes
# itself); this mount just needs to be writable so the CLI can.
- ${ROBOCO_HOST_KIMI_DIR:-/home/renzof/.kimi-code}:${ROBOCO_HOST_KIMI_DIR:-/home/renzof/.kimi-code}
# Shared config directory for MCP configs (writable)
- ${ROBOCO_DATA_DIR:-./data}/mcp-configs:/app/mcp-configs
- ${ROBOCO_DATA_DIR:-./data}/vault:/app/vault
@@ -752,6 +786,8 @@ services:
# Per-agent GEMINI usage capture: each Gemini agent writes usage.json
# under <agent_id>/; the finalizer reads the captured tokens/cost back here.
- ${ROBOCO_DATA_DIR:-./data}/gemini-usage:/data/gemini-usage
# Per-agent KIMI usage capture — same shape as grok/codex/gemini-usage.
- ${ROBOCO_DATA_DIR:-./data}/kimi-usage:/data/kimi-usage
# Persistent logs — survive `docker compose down/up`. Orchestrator and
# each spawned agent write structured logs here so we can audit past
# runs instead of relying on ephemeral `docker logs`.