kimi-plugin-cc 2.2.1 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +14 -0
- package/README.md +5 -5
- package/dist/cli-client.js +9 -0
- package/dist/commands/cli-helpers.js +2 -1
- package/dist/hooks/config-safety.js +3 -2
- package/dist/kimi-engine.js +1 -0
- package/dist/stream-json.js +16 -0
- package/dist/version.js +1 -1
- package/docs/registry-releases.md +7 -5
- package/docs/safety.md +5 -3
- package/package.json +1 -1
- package/plugins/kimi-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/kimi-codex/dist/cli-client.js +9 -0
- package/plugins/kimi-codex/dist/commands/cli-helpers.js +2 -1
- package/plugins/kimi-codex/dist/hooks/config-safety.js +3 -2
- package/plugins/kimi-codex/dist/kimi-engine.js +1 -0
- package/plugins/kimi-codex/dist/stream-json.js +16 -0
- package/plugins/kimi-codex/dist/version.js +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kimi",
|
|
3
3
|
"description": "Claude Code plugin that delegates read-only review, challenge, free-form ask, and write-capable rescue work to the local kimi-code CLI. Includes an opt-in stop-time review gate and a PreToolUse hook that enforces per-command safety.",
|
|
4
|
-
"version": "2.2.
|
|
4
|
+
"version": "2.2.2",
|
|
5
5
|
"homepage": "https://github.com/linxule/kimi-plugin-cc",
|
|
6
6
|
"repository": "https://github.com/linxule/kimi-plugin-cc",
|
|
7
7
|
"license": "Apache-2.0",
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
> **Post-1.0 release history (v1.0.1 -> present) lives in [ROADMAP-TO-GA.md § Post-GA audit log](./ROADMAP-TO-GA.md#post-ga-audit-log)** and the "Version" / "Upstream compat" lines of [AGENTS.md](./AGENTS.md). Docs-only kimi-code compat checkups that don't bump the plugin version (e.g. the 0.14.2 / 0.14.3 patches) are recorded there, not here. Notable releases are summarized below; the GA entry and full pre-GA detail follow.
|
|
4
4
|
|
|
5
|
+
## 2.2.2 — 2026-10-22
|
|
6
|
+
|
|
7
|
+
- Certify exact kimi-code 2.3.0 for all eight native-v2 operations after its
|
|
8
|
+
source scan, plan-ON/OFF controls and full candidate smoke; legacy support
|
|
9
|
+
remains capped at 0.41.x. See [evidence](docs/upstream-2.3.0-certification.md).
|
|
10
|
+
|
|
11
|
+
- Preserve CLI 2.3.0's stdout-only occupied-session refusal as bounded structured
|
|
12
|
+
diagnostics, without treating it as prose, session lineage or an exit-status
|
|
13
|
+
override. Marker-first provenance checks are unchanged.
|
|
14
|
+
- Audit and pin the new stale-session reload path. Concurrent edits to trusted
|
|
15
|
+
operator journals remain an explicit residual; no new hook bypass within the
|
|
16
|
+
existing trust boundary was demonstrated. Clarify the no-plan certification
|
|
17
|
+
gates and remove stale ordering-gate instructions.
|
|
18
|
+
|
|
5
19
|
## 2.2.1 — 2026-10-15
|
|
6
20
|
|
|
7
21
|
- Request per-run thinking effort with `--thinking <effort>` through the upstream environment binding; persist requested effort and replay it in detached workers without changing saved defaults. The review gate requests `off` by default; provider/model no-op cases remain explicit.
|
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ You need:
|
|
|
40
40
|
- macOS or Linux
|
|
41
41
|
- Claude Code or Codex with plugin support
|
|
42
42
|
- Node.js 22.5 or newer
|
|
43
|
-
- Kimi Code CLI 2.
|
|
43
|
+
- Kimi Code CLI 2.3.0 (2.2.0 also certified), the recommended version for plugin 2.2.2
|
|
44
44
|
|
|
45
45
|
Windows is not currently supported. Check your versions in a terminal:
|
|
46
46
|
|
|
@@ -108,7 +108,7 @@ needed to use the package. Kimi Code CLI and Node are still prerequisites.
|
|
|
108
108
|
For an explicitly versioned local Claude Code plugin:
|
|
109
109
|
|
|
110
110
|
```sh
|
|
111
|
-
npm install --prefix ~/.local/share/kimi-plugin-cc kimi-plugin-cc@2.2.
|
|
111
|
+
npm install --prefix ~/.local/share/kimi-plugin-cc kimi-plugin-cc@2.2.2
|
|
112
112
|
claude --plugin-dir ~/.local/share/kimi-plugin-cc/node_modules/kimi-plugin-cc
|
|
113
113
|
```
|
|
114
114
|
|
|
@@ -249,7 +249,7 @@ Contributors need Bun to run `bun run check`. The detailed engineering documents
|
|
|
249
249
|
- macOS 或 Linux
|
|
250
250
|
- 支持插件的 Claude Code 或 Codex
|
|
251
251
|
- Node.js 22.5 或更高版本
|
|
252
|
-
- Kimi Code CLI 2.
|
|
252
|
+
- Kimi Code CLI 2.3.0(2.2.0 亦已认证),这是插件 2.2.2 的推荐版本
|
|
253
253
|
|
|
254
254
|
目前不支持 Windows。在终端检查版本:
|
|
255
255
|
|
|
@@ -433,7 +433,7 @@ Il vous faut :
|
|
|
433
433
|
- macOS ou Linux
|
|
434
434
|
- une version de Claude Code ou de Codex prenant en charge les plugins
|
|
435
435
|
- Node.js 22.5 ou une version ultérieure
|
|
436
|
-
- Kimi Code CLI 2.
|
|
436
|
+
- Kimi Code CLI 2.3.0 (2.2.0 également certifiée), la version recommandée pour le plugin 2.2.2
|
|
437
437
|
|
|
438
438
|
Windows n'est pas pris en charge actuellement. Vérifiez les versions dans un terminal :
|
|
439
439
|
|
|
@@ -617,7 +617,7 @@ Les contributeurs ont besoin de Bun pour exécuter `bun run check`. La documenta
|
|
|
617
617
|
- macOS または Linux
|
|
618
618
|
- プラグインに対応した Claude Code または Codex
|
|
619
619
|
- Node.js 22.5 以降
|
|
620
|
-
- Kimi Code CLI 2.
|
|
620
|
+
- Kimi Code CLI 2.3.0(2.2.0 も認証済み。プラグイン 2.2.2 の推奨バージョン)
|
|
621
621
|
|
|
622
622
|
現在、Windows には対応していません。ターミナルでバージョンを確認します。
|
|
623
623
|
|
package/dist/cli-client.js
CHANGED
|
@@ -126,6 +126,7 @@ export async function runCliPrompt(opts) {
|
|
|
126
126
|
let stderrTail = "";
|
|
127
127
|
let announcedSessionId;
|
|
128
128
|
let announcedGoalSummary;
|
|
129
|
+
let announcedCliError;
|
|
129
130
|
let announcedSystemVersion;
|
|
130
131
|
const hookMonitor = createHookEscapeMonitor({ commandLabel: opts.commandLabel,
|
|
131
132
|
operationKind: opts.executionPlan.operationKind, trustedWorkspaceRoot: opts.trustedWorkspaceRoot, cwd: opts.cwd });
|
|
@@ -190,6 +191,13 @@ export async function runCliPrompt(opts) {
|
|
|
190
191
|
for (const outcome of outcomes) {
|
|
191
192
|
if (engineMismatchDetected)
|
|
192
193
|
return;
|
|
194
|
+
if (outcome.cliError !== undefined) {
|
|
195
|
+
if (requireMarkerBeforeOutput("a CLI error record"))
|
|
196
|
+
return;
|
|
197
|
+
announcedCliError ??= outcome.cliError;
|
|
198
|
+
appendLogLine({ event: "cli_error", ...outcome.cliError });
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
193
201
|
if (outcome.unknownRecord !== undefined) {
|
|
194
202
|
// H3 forward-compat: a stream-json line with a role we don't model
|
|
195
203
|
// (a future kimi-code role). Log it for diagnostics but keep it OUT of
|
|
@@ -609,6 +617,7 @@ export async function runCliPrompt(opts) {
|
|
|
609
617
|
settledAt: 0, // Filled at settlement, after the teardown barrier.
|
|
610
618
|
sessionId,
|
|
611
619
|
goalSummary: announcedGoalSummary,
|
|
620
|
+
cliError: announcedCliError,
|
|
612
621
|
systemVersion: announcedSystemVersion,
|
|
613
622
|
observedEngine: announcedSystemVersion !== undefined
|
|
614
623
|
? "native-v2"
|
|
@@ -99,7 +99,7 @@ export function assertCliResultSuccess(result, stage) {
|
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
if (result.exitCode !== 0) {
|
|
102
|
-
const tail = result.stderrTail.trim();
|
|
102
|
+
const tail = result.cliError?.message ?? result.stderrTail.trim();
|
|
103
103
|
throw new RuntimeError("CLI_NONZERO_EXIT", [
|
|
104
104
|
`kimi subprocess exited with code ${result.exitCode}`,
|
|
105
105
|
result.signal ? ` (signal ${result.signal})` : "",
|
|
@@ -110,6 +110,7 @@ export function assertCliResultSuccess(result, stage) {
|
|
|
110
110
|
signal: result.signal,
|
|
111
111
|
record_count: result.records.length,
|
|
112
112
|
malformed_count: result.malformed.length,
|
|
113
|
+
...(result.cliError !== undefined && { cli_error: result.cliError }),
|
|
113
114
|
stderr_tail_len: result.stderrTail.length,
|
|
114
115
|
},
|
|
115
116
|
});
|
|
@@ -593,7 +593,7 @@ function validateVersionSensitiveEvents(events, version) {
|
|
|
593
593
|
return invalidHookSet(`version-sensitive event ${JSON.stringify(first.event)} requires a verified kimi-code version`, first.entry, first.line);
|
|
594
594
|
}
|
|
595
595
|
// Exact schemas reviewed at 2.0.0 (1b89e4b0), 2.0.1 (caf7d4e2),
|
|
596
|
-
// 2.0.2 (9d07f634), 2.1.0 (52437299), 2.1.1 (f67e6398)
|
|
596
|
+
// 2.0.2 (9d07f634), 2.1.0 (52437299), 2.1.1 (f67e6398), 2.2.0 (472192c3) and 2.3.0 (b5e28fd6):
|
|
597
597
|
// the additive events and HookDefSchema are unchanged. Require the full
|
|
598
598
|
// version string AND matching components; no inferred 2.x compatibility.
|
|
599
599
|
if (version.major === 2 && ((version.minor === 0 && ((version.version === "2.0.0" && version.patch === 0) ||
|
|
@@ -601,7 +601,8 @@ function validateVersionSensitiveEvents(events, version) {
|
|
|
601
601
|
(version.version === "2.0.2" && version.patch === 2))) ||
|
|
602
602
|
(version.minor === 1 && ((version.version === "2.1.0" && version.patch === 0) ||
|
|
603
603
|
(version.version === "2.1.1" && version.patch === 1))) ||
|
|
604
|
-
(version.minor === 2 && ((version.version === "2.2.0" && version.patch === 0)))
|
|
604
|
+
(version.minor === 2 && ((version.version === "2.2.0" && version.patch === 0))) ||
|
|
605
|
+
(version.minor === 3 && version.version === "2.3.0" && version.patch === 0))) {
|
|
605
606
|
return { valid: true };
|
|
606
607
|
}
|
|
607
608
|
if (version.major !== 0) {
|
package/dist/kimi-engine.js
CHANGED
package/dist/stream-json.js
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
// {"role":"meta","type":"turn.step.retrying","failed_attempt":1,"next_attempt":2,"max_attempts":3,"delay_ms":300,"error_name":"APIProviderRateLimitError","error_message":"...","status_code":429}
|
|
13
13
|
// {"role":"meta","type":"system.version","version":"0.24.2"} // experimental v2 only; modeled since v1.8.5 (SystemVersionRecord), filtered like other meta
|
|
14
14
|
//
|
|
15
|
+
// {"type":"error","code":"session.occupied","message":"...","details":{...}} // 2.3.0; stdout-only refusal, exit 4
|
|
16
|
+
//
|
|
15
17
|
// Notes on what does and does not appear here:
|
|
16
18
|
// - The session.resume_hint meta record is NEW in kimi-code 0.2.0
|
|
17
19
|
// (introduced at run-prompt.ts:477-505 in 0.2.0; the writer region —
|
|
@@ -263,6 +265,20 @@ function parseLine(line) {
|
|
|
263
265
|
if (role === undefined && parsed["type"] === "goal.summary") {
|
|
264
266
|
return validateGoalSummary(parsed, line);
|
|
265
267
|
}
|
|
268
|
+
if (role === undefined && parsed["type"] === "error") {
|
|
269
|
+
if (typeof parsed["code"] !== "string" || parsed["code"].length === 0 ||
|
|
270
|
+
typeof parsed["message"] !== "string" || parsed["message"].length === 0 ||
|
|
271
|
+
(parsed["details"] !== undefined && !isRecord(parsed["details"]))) {
|
|
272
|
+
return { malformedLine: line, malformedReason: "error record field has unexpected type" };
|
|
273
|
+
}
|
|
274
|
+
// Keep bounded diagnostic fields only; holder metadata is not needed and
|
|
275
|
+
// must not become a session-id source or be copied into persisted errors.
|
|
276
|
+
return { cliError: {
|
|
277
|
+
type: "error",
|
|
278
|
+
code: parsed["code"].slice(0, 200),
|
|
279
|
+
message: parsed["message"].slice(0, 4000),
|
|
280
|
+
} };
|
|
281
|
+
}
|
|
266
282
|
// H3 forward-compat: a non-empty string role we don't model (a role a future
|
|
267
283
|
// kimi-code adds). Surface it out-of-band on the unknownRecord channel —
|
|
268
284
|
// tolerated, not malformed — so the parser keeps working and the diagnostic
|
package/dist/version.js
CHANGED
|
@@ -6,10 +6,12 @@ remain available. The package has no install scripts and no separate CLI.
|
|
|
6
6
|
|
|
7
7
|
## Publishing status
|
|
8
8
|
|
|
9
|
-
As of October 15, 2026, [2.2.
|
|
10
|
-
the release-event run of `publish.yml` (run
|
|
11
|
-
provenance statement (sigstore log index
|
|
12
|
-
|
|
9
|
+
As of October 15, 2026, [2.2.1 is live on npm](https://www.npmjs.com/package/kimi-plugin-cc/v/2.2.1), published by
|
|
10
|
+
the release-event run of `publish.yml` (run 38720071707) through GitHub Actions OIDC with a signed
|
|
11
|
+
provenance statement (sigstore log index 3263398504; tarball shasum
|
|
12
|
+
`03907c66d440155763a860ab52b5107c0233938b`, registry propagation took a few minutes this time).
|
|
13
|
+
2.2.0 (same day, run 38658918855, log index 3256863983) was the first release where the tag-triggered
|
|
14
|
+
path worked end to end without a manual dispatch; 2.0.8 (same day, run 38650044033) was the first
|
|
13
15
|
OIDC publication; 2.0.7 (September 26) was the hand-published bootstrap.
|
|
14
16
|
The first upload used the validated GitHub Actions artifact and interactive npm
|
|
15
17
|
authentication. Its public tarball matched that artifact byte-for-byte, and a
|
|
@@ -19,7 +21,7 @@ The trusted publisher is configured for `linxule/kimi-plugin-cc`, workflow
|
|
|
19
21
|
`publish.yml`, environment `npm`, with direct publishing allowed.
|
|
20
22
|
`NPM_TRUSTED_PUBLISHING=true` is enabled in GitHub Actions. Future GitHub releases
|
|
21
23
|
use short-lived OIDC credentials, without a stored npm token or interactive 2FA.
|
|
22
|
-
|
|
24
|
+
OIDC publication is established; never republish an existing version.
|
|
23
25
|
|
|
24
26
|
**2026-10-15 status.** The `v2.0.8` release triggered the first OIDC attempt. It
|
|
25
27
|
failed twice on the publish step for reasons unrelated to the package: current
|
package/docs/safety.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Safety
|
|
2
2
|
|
|
3
|
-
This guide describes the
|
|
3
|
+
This guide describes the current checkout runtime; 2.3.0 certification is unreleased. Read-only tasks deny file writes and shell commands. Rescue and pursue can edit your workspace. Write-swarm returns a patch from a temporary Git worktree.
|
|
4
4
|
|
|
5
|
-
Native agent-core-v2 is certified at exact CLI versions `0.42.0`, `0.43.0`, `0.43.1`, `2.0.0`, `2.0.1`, `2.0.2`, `2.1.0`,
|
|
5
|
+
Native agent-core-v2 is certified at exact CLI versions `0.42.0`, `0.43.0`, `0.43.1`, `2.0.0`, `2.0.1`, `2.0.2`, `2.1.0`, `2.1.1`, `2.2.0`, and `2.3.0`, with plan mode disabled. The [runtime certification table](../runtime/kimi-engine.ts) controls routing. The hook is not an operating-system sandbox.
|
|
6
6
|
|
|
7
7
|
## Why the safety story is hook-based
|
|
8
8
|
|
|
@@ -156,6 +156,8 @@ Provenance: a native-v2 plan requires the `system.version` marker as the first s
|
|
|
156
156
|
|
|
157
157
|
Residuals, unchanged from v1 and stated plainly: `config.toml` and the session journals are trusted operator state (an actor who can write them could already delete the `[[hooks]]` entry); the upstream hook runner fails open on its own internal errors; the plan-path comparison does not realpath (a symlink there would need a prior hook-allowed write). Native plan mode, tower, subagent fork, Remote Control and `--add-dir` are out of scope.
|
|
158
158
|
|
|
159
|
+
In CLI 2.3.0, stale-session retry can reread those same journals. Do not concurrently operate on or edit a plugin-managed session from another client. The upstream session lock is not a security boundary; no parent-side rescan can make that reload atomic.
|
|
160
|
+
|
|
159
161
|
## The rescue allowlist
|
|
160
162
|
|
|
161
163
|
For `/kimi:rescue`, the hook delegates to [`evaluateRescueHookRequest`](../runtime/rescue-approval.ts). The allowlist has been extended since the original Wire-transport implementation. Highlights:
|
|
@@ -368,7 +370,7 @@ If you find a way to coax /kimi:review, /kimi:challenge, /kimi:review_gate, or /
|
|
|
368
370
|
|
|
369
371
|
**Hook-escape monitor** (§1): the cli-client replays the pure hook policy on every streamed `tool_calls` entry; a call the policy denies whose tool result is not the hook's denial (byte-exact, or with upstream's repeat-breaker `<system-reminder>` decoration / handoff text) is recorded as `mismatch`, and a denied call still without a result at settlement as `unresolved`. Findings are **detection evidence, never a failure**: logged (`hook_escape`), persisted on the job row (`hook_escapes`, JSON), exposed by `status`/`result --json`, printed as a stderr `safety hook notice`, and carried in timeout details; the run continues, the job's outcome is unchanged, and the review gate stays fail-open and only annotates. The stream has no outcome field, so a mismatch is equally an upstream pre-hook rejection (unknown tool, disabled tool, invalid args, sensitive path, per-tool resolve errors), a coexisting hook or permission policy blocking first, or hook drift — failing the job needs positive execution evidence this stream does not provide. Streamed calls under read-only labels are covered (swarm subagents are in-process, not streamed); write labels only for the pure denials (plan/goal tools).
|
|
370
372
|
|
|
371
|
-
A denied attempt alone is not a finding: the hook's denial text in the corresponding tool result (byte-exact, or carrying upstream's repeat-breaker decoration) proves enforcement and clears it. Anything else is recorded as `mismatch` with a 200-character excerpt; a denied call with no result at settlement as `unresolved`. **What a finding means:** the model received something other than the managed denial. On certified 2.2.0 that is produced just as readily by calls upstream rejects before the hook runs (`Tool "LS" not found`, `Invalid args for tool …`, the sensitive-path `PathSecurityError` for `.env`, per-tool resolve errors, `Tool skipped because a previous tool call stopped the turn.`), by a coexisting PreToolUse hook ahead of the managed block or an upstream permission policy blocking first, or by a cancel/budget abort landing before the result — none of which executed anything — as by a hook that failed open. Because the stream carries no outcome field, the plugin cannot tell these apart, so it reports and does not fail: the job completes or fails on its own merits, `status`/`result --json` carry `hook_escapes`, stderr prints a `safety hook notice`, and the review gate annotates `systemMessage` without changing its decision. Treat a finding as a prompt to run `/kimi:setup --check` and read the excerpt, not as proof of a breach; treat a *recurring* `mismatch` whose excerpt looks like tool output (`Wrote N bytes to …`) as a drifted hook. Coverage is streamed calls under read-only labels and pure denials under write labels — not filesystem-dependent rescue allowlist decisions, not swarm subagent calls (in-process, never streamed). Non-vacuous live control (CLI 2.2.0, 2026-10-15): with the hook command pointed at a nonexistent script upstream failed open, `Write` created the file, and the finding was `mismatch` with excerpt `Wrote 7 bytes to ESCAPE.txt`; with the hook intact the same prompt produced the byte-exact denial and no finding. Enforcement (stopping the run, failing the job) is deliberately not shipped: it needs positive execution evidence. The
|
|
373
|
+
A denied attempt alone is not a finding: the hook's denial text in the corresponding tool result (byte-exact, or carrying upstream's repeat-breaker decoration) proves enforcement and clears it. Anything else is recorded as `mismatch` with a 200-character excerpt; a denied call with no result at settlement as `unresolved`. **What a finding means:** the model received something other than the managed denial. On certified 2.2.0 that is produced just as readily by calls upstream rejects before the hook runs (`Tool "LS" not found`, `Invalid args for tool …`, the sensitive-path `PathSecurityError` for `.env`, per-tool resolve errors, `Tool skipped because a previous tool call stopped the turn.`), by a coexisting PreToolUse hook ahead of the managed block or an upstream permission policy blocking first, or by a cancel/budget abort landing before the result — none of which executed anything — as by a hook that failed open. Because the stream carries no outcome field, the plugin cannot tell these apart, so it reports and does not fail: the job completes or fails on its own merits, `status`/`result --json` carry `hook_escapes`, stderr prints a `safety hook notice`, and the review gate annotates `systemMessage` without changing its decision. Treat a finding as a prompt to run `/kimi:setup --check` and read the excerpt, not as proof of a breach; treat a *recurring* `mismatch` whose excerpt looks like tool output (`Wrote N bytes to …`) as a drifted hook. Coverage is streamed calls under read-only labels and pure denials under write labels — not filesystem-dependent rescue allowlist decisions, not swarm subagent calls (in-process, never streamed). Non-vacuous live control (CLI 2.2.0, 2026-10-15): with the hook command pointed at a nonexistent script upstream failed open, `Write` created the file, and the finding was `mismatch` with excerpt `Wrote 7 bytes to ESCAPE.txt`; with the hook intact the same prompt produced the byte-exact denial and no finding. Enforcement (stopping the run, failing the job) is deliberately not shipped: it needs positive execution evidence. The upstream ask, filed as MoonshotAI/kimi-code#4241, is an `outcome: executed|vetoed|rejected` field on print-mode tool records; a plugin-side alternative is a per-job trace the hook writes before it exits.
|
|
372
374
|
|
|
373
375
|
## Review-gate thinking request
|
|
374
376
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kimi",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "Codex plugin that delegates review, challenge, ask, rescue, pursue, and swarm workflows to the local kimi-code CLI through the kimi-plugin-cc companion runtime.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "linxule"
|
|
@@ -126,6 +126,7 @@ export async function runCliPrompt(opts) {
|
|
|
126
126
|
let stderrTail = "";
|
|
127
127
|
let announcedSessionId;
|
|
128
128
|
let announcedGoalSummary;
|
|
129
|
+
let announcedCliError;
|
|
129
130
|
let announcedSystemVersion;
|
|
130
131
|
const hookMonitor = createHookEscapeMonitor({ commandLabel: opts.commandLabel,
|
|
131
132
|
operationKind: opts.executionPlan.operationKind, trustedWorkspaceRoot: opts.trustedWorkspaceRoot, cwd: opts.cwd });
|
|
@@ -190,6 +191,13 @@ export async function runCliPrompt(opts) {
|
|
|
190
191
|
for (const outcome of outcomes) {
|
|
191
192
|
if (engineMismatchDetected)
|
|
192
193
|
return;
|
|
194
|
+
if (outcome.cliError !== undefined) {
|
|
195
|
+
if (requireMarkerBeforeOutput("a CLI error record"))
|
|
196
|
+
return;
|
|
197
|
+
announcedCliError ??= outcome.cliError;
|
|
198
|
+
appendLogLine({ event: "cli_error", ...outcome.cliError });
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
193
201
|
if (outcome.unknownRecord !== undefined) {
|
|
194
202
|
// H3 forward-compat: a stream-json line with a role we don't model
|
|
195
203
|
// (a future kimi-code role). Log it for diagnostics but keep it OUT of
|
|
@@ -609,6 +617,7 @@ export async function runCliPrompt(opts) {
|
|
|
609
617
|
settledAt: 0, // Filled at settlement, after the teardown barrier.
|
|
610
618
|
sessionId,
|
|
611
619
|
goalSummary: announcedGoalSummary,
|
|
620
|
+
cliError: announcedCliError,
|
|
612
621
|
systemVersion: announcedSystemVersion,
|
|
613
622
|
observedEngine: announcedSystemVersion !== undefined
|
|
614
623
|
? "native-v2"
|
|
@@ -99,7 +99,7 @@ export function assertCliResultSuccess(result, stage) {
|
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
if (result.exitCode !== 0) {
|
|
102
|
-
const tail = result.stderrTail.trim();
|
|
102
|
+
const tail = result.cliError?.message ?? result.stderrTail.trim();
|
|
103
103
|
throw new RuntimeError("CLI_NONZERO_EXIT", [
|
|
104
104
|
`kimi subprocess exited with code ${result.exitCode}`,
|
|
105
105
|
result.signal ? ` (signal ${result.signal})` : "",
|
|
@@ -110,6 +110,7 @@ export function assertCliResultSuccess(result, stage) {
|
|
|
110
110
|
signal: result.signal,
|
|
111
111
|
record_count: result.records.length,
|
|
112
112
|
malformed_count: result.malformed.length,
|
|
113
|
+
...(result.cliError !== undefined && { cli_error: result.cliError }),
|
|
113
114
|
stderr_tail_len: result.stderrTail.length,
|
|
114
115
|
},
|
|
115
116
|
});
|
|
@@ -593,7 +593,7 @@ function validateVersionSensitiveEvents(events, version) {
|
|
|
593
593
|
return invalidHookSet(`version-sensitive event ${JSON.stringify(first.event)} requires a verified kimi-code version`, first.entry, first.line);
|
|
594
594
|
}
|
|
595
595
|
// Exact schemas reviewed at 2.0.0 (1b89e4b0), 2.0.1 (caf7d4e2),
|
|
596
|
-
// 2.0.2 (9d07f634), 2.1.0 (52437299), 2.1.1 (f67e6398)
|
|
596
|
+
// 2.0.2 (9d07f634), 2.1.0 (52437299), 2.1.1 (f67e6398), 2.2.0 (472192c3) and 2.3.0 (b5e28fd6):
|
|
597
597
|
// the additive events and HookDefSchema are unchanged. Require the full
|
|
598
598
|
// version string AND matching components; no inferred 2.x compatibility.
|
|
599
599
|
if (version.major === 2 && ((version.minor === 0 && ((version.version === "2.0.0" && version.patch === 0) ||
|
|
@@ -601,7 +601,8 @@ function validateVersionSensitiveEvents(events, version) {
|
|
|
601
601
|
(version.version === "2.0.2" && version.patch === 2))) ||
|
|
602
602
|
(version.minor === 1 && ((version.version === "2.1.0" && version.patch === 0) ||
|
|
603
603
|
(version.version === "2.1.1" && version.patch === 1))) ||
|
|
604
|
-
(version.minor === 2 && ((version.version === "2.2.0" && version.patch === 0)))
|
|
604
|
+
(version.minor === 2 && ((version.version === "2.2.0" && version.patch === 0))) ||
|
|
605
|
+
(version.minor === 3 && version.version === "2.3.0" && version.patch === 0))) {
|
|
605
606
|
return { valid: true };
|
|
606
607
|
}
|
|
607
608
|
if (version.major !== 0) {
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
// {"role":"meta","type":"turn.step.retrying","failed_attempt":1,"next_attempt":2,"max_attempts":3,"delay_ms":300,"error_name":"APIProviderRateLimitError","error_message":"...","status_code":429}
|
|
13
13
|
// {"role":"meta","type":"system.version","version":"0.24.2"} // experimental v2 only; modeled since v1.8.5 (SystemVersionRecord), filtered like other meta
|
|
14
14
|
//
|
|
15
|
+
// {"type":"error","code":"session.occupied","message":"...","details":{...}} // 2.3.0; stdout-only refusal, exit 4
|
|
16
|
+
//
|
|
15
17
|
// Notes on what does and does not appear here:
|
|
16
18
|
// - The session.resume_hint meta record is NEW in kimi-code 0.2.0
|
|
17
19
|
// (introduced at run-prompt.ts:477-505 in 0.2.0; the writer region —
|
|
@@ -263,6 +265,20 @@ function parseLine(line) {
|
|
|
263
265
|
if (role === undefined && parsed["type"] === "goal.summary") {
|
|
264
266
|
return validateGoalSummary(parsed, line);
|
|
265
267
|
}
|
|
268
|
+
if (role === undefined && parsed["type"] === "error") {
|
|
269
|
+
if (typeof parsed["code"] !== "string" || parsed["code"].length === 0 ||
|
|
270
|
+
typeof parsed["message"] !== "string" || parsed["message"].length === 0 ||
|
|
271
|
+
(parsed["details"] !== undefined && !isRecord(parsed["details"]))) {
|
|
272
|
+
return { malformedLine: line, malformedReason: "error record field has unexpected type" };
|
|
273
|
+
}
|
|
274
|
+
// Keep bounded diagnostic fields only; holder metadata is not needed and
|
|
275
|
+
// must not become a session-id source or be copied into persisted errors.
|
|
276
|
+
return { cliError: {
|
|
277
|
+
type: "error",
|
|
278
|
+
code: parsed["code"].slice(0, 200),
|
|
279
|
+
message: parsed["message"].slice(0, 4000),
|
|
280
|
+
} };
|
|
281
|
+
}
|
|
266
282
|
// H3 forward-compat: a non-empty string role we don't model (a role a future
|
|
267
283
|
// kimi-code adds). Surface it out-of-band on the unknownRecord channel —
|
|
268
284
|
// tolerated, not malformed — so the parser keeps working and the diagnostic
|