Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/providers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ For the architectural picture, see `../architecture.md`.
| [KiloCode](kilo-code.md) | JSON | `src/providers/kilo-code.ts` | `tests/providers/kilo-code.test.ts` |
| [Kiro](kiro.md) | JSON | `src/providers/kiro.ts` | `tests/providers/kiro.test.ts` |
| [Kimi](kimi.md) | JSONL | `src/providers/kimi.ts` | `tests/providers/kimi.test.ts` |
| [Kimi Code](kimicode.md) | JSONL | `src/providers/kimicode.ts` | `tests/providers/kimicode.test.ts` |
| [LingTai TUI](lingtai-tui.md) | JSONL | `src/providers/lingtai-tui.ts` | `tests/providers/lingtai-tui.test.ts` |
| [Mistral Vibe](mistral-vibe.md) | JSON / JSONL | `src/providers/mistral-vibe.ts` | `tests/providers/mistral-vibe.test.ts` |
| [OpenClaw](openclaw.md) | JSONL | `src/providers/openclaw.ts` | `tests/providers/openclaw.test.ts` |
Expand Down
73 changes: 73 additions & 0 deletions docs/providers/kimicode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Kimi Code

MoonshotAI Kimi Code local session usage and tool activity.

- **Source:** `src/providers/kimicode.ts`
- **Loading:** eager
- **Test:** `tests/providers/kimicode.test.ts`

## Where it reads from

The provider reads `~/.kimi-code` by default and honors the Kimi Code CLI's `KIMI_CODE_HOME` environment variable. It scans:

```text
$KIMI_CODE_HOME/sessions/wd_*/session_*/
├── state.json
└── agents/<agent-id>/wire.jsonl
```

Every agent wire is a cache source. Main-agent and subagent calls share the session ID from the `session_*` directory. `state.json.workDir` supplies the project name and path. `probeRoots()` reports the resolved Kimi Code home for `codeburn doctor` even when there are no sessions.

## Storage format

`wire.jsonl` contains one event per line. The parser uses:

- `turn.prompt.input` for the current user message.
- `llm.request.model` for the real model ID and the turn prefix from `turnStep`.
- `context.append_loop_event.event` when its type is `tool.call`; the event's `name` feeds the tool breakdown.
- `usage.record.usage` for billed tokens.

Token fields map as follows:

| Kimi Code | CodeBurn |
|---|---|
| `inputOther` | input |
| `output` | output |
| `inputCacheRead` | cache read and cached input |
| `inputCacheCreation` | cache write |

`usage.record.model` is only the configured alias. The parser resolves that alias through observed `llm.request` events to obtain the real model ID used for pricing and reports, falling back to the nearest preceding request when the alias is empty or unknown. Kimi Code records no cost, so CodeBurn computes it from the four token categories with `calculateCost` and marks it estimated.

Malformed JSONL lines are skipped independently. A failed session containing retrying `llm.request` events but no `usage.record` events emits no calls and therefore contributes zero usage. Retry `attempt` values are not interpreted.

## Caching

Kimi Code is an eager provider using the shared session cache. Each agent's `wire.jsonl` is fingerprinted separately. `KIMI_CODE_HOME` and the Kimi Code parser version participate in the provider cache fingerprint.

## Deduplication

Usage calls use `kimicode:<session-id>:<agent-id>:<line-number>:<usage-ordinal>`. Including the agent ID keeps main-agent and subagent events distinct, while stable line positions prevent a wire from being counted twice across parses.

This agent-and-position-scoped key relies on the store invariant that each agent's `usage.record` events appear only in its own `wire.jsonl`, as identified by the `state.json` agents map. If a future Kimi Code version mirrors subagent usage into the main wire, the key must become content-scoped.

## Quirks

- Multi-turn continuations append to the same wire. The numeric prefix of `llm.request.turnStep` groups multiple model steps into the correct turn.
- Tools are attached to the next `usage.record` in the same wire and then cleared, so each `tool.call` contributes once.
- Kimi Code is the successor to the legacy `kimi-cli`. Kimi Code migrates predecessor configuration and sessions into its own store; this provider intentionally does not parse the old `~/.kimi` layout.

## When fixing a bug here

1. Keep real-model attribution based on `llm.request.model`; never report the alias from `usage.record.model`.
2. Test main and subagent wires together with a shared deduplication set.
3. Preserve malformed-line and retry-only coverage when adding event variants.
4. Keep fixtures sanitized and rooted in a temporary `KIMI_CODE_HOME`.

## Subagent accounting (verified at source)

Subagent token usage is recorded only in the subagent's own `wire.jsonl`.
When a subagent completes, the parent's wire receives a `subagent.completed`
summary event (informational, ignored by this parser), never a `usage.record`
mirroring the child's tokens (see MoonshotAI/kimi-code,
`packages/agent-core/src/session/subagent-host.ts`). Summing `usage.record`
events across all agent wires therefore does not double count.
3 changes: 2 additions & 1 deletion src/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ibmBob } from './ibm-bob.js'
import { kiloCode } from './kilo-code.js'
import { kiro } from './kiro.js'
import { kimi } from './kimi.js'
import { kimicode } from './kimicode.js'
import { lingtaiTui } from './lingtai-tui.js'
import { mistralVibe } from './mistral-vibe.js'
import { mux } from './mux.js'
Expand Down Expand Up @@ -189,7 +190,7 @@ async function loadZed(): Promise<Provider | null> {
}
}

const coreProviders: Provider[] = [claude, cline, codewhale, codebuff, codex, copilot, devin, droid, gemini, hermes, ibmBob, kiloCode, kiro, kimi, lingtaiTui, mistralVibe, mux, openclaw, openDesign, pi, omp, qwen, quickdesk, rooCode, zerostack, grok]
const coreProviders: Provider[] = [claude, cline, codewhale, codebuff, codex, copilot, devin, droid, gemini, hermes, ibmBob, kiloCode, kiro, kimi, kimicode, lingtaiTui, mistralVibe, mux, openclaw, openDesign, pi, omp, qwen, quickdesk, rooCode, zerostack, grok]

// Lazily loaded providers, listed by name so --provider validation works even
// when an optional module fails to load. Must stay in sync with getAllProviders.
Expand Down
Loading