Repository navigation
feat: kimi three-mode alignment — native plugin mode - #982
Conversation
📦 Built Package ArtifactBranch: Option A — Install from npm PR tag (recommended)npm install -g billion-context@pr-982Each push to this PR publishes a new version under the Option B — Download artifact
tar xzf billion-context-pr982.tgz
npm install -g packageInstall instructions are refreshed on each push. |
[bot] 🏷 收到,开始核验这个 PR(不重做)。初步观察:分支 |
[bot] 🏷 Verification complete — I did not redo the work (the What I verified
Code review (focus areas)
Minor findings (report-only, nothing fixed)
Neither affects behavior. Per §7.4 this is a 一句话总结:已按 #963 批准的设计完整核验 kimi 三模式对齐实现——config.toml 改写路径防篡改守卫完备、wire/plugin 两种压缩模式行为均正确、rebase 到最新 master 后 typecheck/全量测试/build 与 CI 8 项检查全部通过,仅发现两处不影响行为的小问题(一处过期注释、一处幂等的重复 unroute 调用),可以合并。 |
Kimi Code (Moonshot) gets the full three-mode treatment like pi/opencode/dsh: launcher (bili kimi, #757), /bili/ URL prefix, and — new — a self-spawning native plugin via 'bili plugin install kimi'. Kimi v2's plugin system is declarative only (kimi.plugin.json: MCP servers, hooks, skills — no in-process JS execution), so the dsh playbook's fetch patch is impossible. The adapted design (approved in-thread): - Installer writes $KIMI_CODE_HOME/plugins/managed/billion-context/kimi.plugin.json (stdio MCP server + SessionStart hook, abs paths into the live package dist) plus an installed.json record; version floor kimi --version >= 2.0.0. - Per-session bootstrap (MCP child of kimi): attach to BILLION_CONTEXT_PROXY or spawn on an ephemeral port, then an idempotent line-surgical managed block in ~/.kimi-code/config.toml — own [providers.bili] cloning the active provider's oauth/api_key reference, [models.bili-kimi] alias, default_model redirect with the previous value recorded; config.toml.bili-bak snapshot once; mkdir lockfile. Kimi's config hot-reload applies the change to live sessions. - Plugin-mode stamping: custom_headers x-bili-plugin=kimi written ONLY after the ACP tool list is verified against the live manifest (round 1 rides wire mode). Static headers can't carry per-request window/model values without going stale on model switch, so runtime-info is reported at bootstrap only (#955 protocol). - Watchdog: 30s probe; attached mode waits forever, spawn mode respawns and re-routes to the new origin; give-up unroutes back to direct upstream. Session end: kimi kills the MCP child -> parent-pid teardown kills the proxy. - Opt-out BILI_NATIVE_KIMI=0. Subagent conversations get separate derived sessions (per-call conversation_id binding, #760 channel). Tests: tests/kimi-native.test.ts (20 tests — plan precedence, toml roundtrips incl. idempotency + user-change preservation, installer under fake home, live proxy integration). Two real bugs found by the tests and fixed: re-apply used to degrade the recorded default_model, and the health probe treated the fresh proxy's pre-first-request 404 as unhealthy.
e529af5 to
7f0df5a
Compare
|
Rebased onto master (post #981): resolved conflicts in README.md / README.zh-CN.md / tsup.config.ts / src/plugin-install.ts / tests/plugin-agent.test.ts — took the union in every case (claude native #964 + kimi native #963 both present). Pre-flight green: typecheck ✅, 1994 tests pass / 0 fail, build ✅. Head: 7f0df5a. |
Fixes #963
What
Kimi Code (Moonshot) now has full three-mode alignment like pi/opencode/dsh:
bili kimilauncher (already there, #757),/bili/URL prefix, and — new — native plugin mode viabili plugin install kimi: no launcher, no env vars, no fixed port for the end user.Why the design deviates from the dsh playbook
Kimi v2's plugin system is declarative only (
kimi.plugin.json: MCP servers, hooks, skills — no in-process JS execution), so the dsh-style global fetch patch is impossible. The adapted design (approved in the #963 thread):$KIMI_CODE_HOME/plugins/managed/billion-context/kimi.plugin.json(stdio MCP servernode <root>/dist/kimi/native-mcp.js+SessionStarthooknode <root>/dist/kimi/bootstrap-hook.js) plus aninstalled.jsonrecord. Version floor:kimi --version≥ 2.0.0 (installer refuses below; launcher still works).BILLION_CONTEXT_PROXYor spawns on an ephemeral port, then rewrites routing with an idempotent line-surgical managed block in~/.kimi-code/config.toml— own[providers.bili]cloning the active provider'soauth/api_keyreference verbatim,[models.bili-kimi]alias, top-leveldefault_modelredirect with the previous value recorded in-block. Original snapshotted toconfig.toml.bili-bakonce; every write under a mkdir lockfile; user content outside the block never touched (§7.3). Kimi's config hot-reload applies changes to live sessions.custom_headers = { x-bili-plugin = "kimi" }is written ONLY after the ACP tool list is verified against the live proxy manifest — round 1 rides wire mode.custom_headerscannot carry per-request window/model headers without going stale on model switch — documented deviation from pi/dsh.BILI_NATIVE_KIMI=0. Subagent conversations get separate derived sessions (per-callconversation_idbinding, feat: per-call conversation_id for MCP tools — let the model supply its session id #760 channel) — kimi exposes no stable session id; documented limitation.New files
src/kimi/toml-edit.ts— pure line-surgery TOML RMW (no parser dependency): managed-block render/apply/unroute with tamper guards + collision throws, route resolution (upstream/auth priority chain incl.KIMI_CODE_BASE_URLenv truth injected by kimi's plugin service), plugin-header stamping.src/kimi/native.ts— plan (kill-switches > attach > spawn), health probe (404 pre-first-request IS healthy for a fresh proxy), lockfile-guarded config rewrite + verify, runtime-info activation, unroute/restore.src/kimi/native-mcp.ts— MCP entry: bootstrap → stamp-after-manifest-verify → ACP tool loop (sharedrunMcpStdio) + respawn/re-route watchdog.src/kimi/bootstrap-hook.ts— SessionStart hook: attach-only opportunistic bootstrap (fail-open, never spawns).tests/kimi-native.test.ts— 20 tests (plan precedence, TOML roundtrips incl. idempotency + user-change preservation, installer under fake home with PATH shim, live-proxy integration incl. runtime-info capture).The tests found two real bugs, both fixed here: re-applying the managed block used to degrade the recorded
default_model(second bootstrap would leave the user stuck on the alias at unroute), and the health probe treated a fresh proxy's pre-first-request 404 as unhealthy.Pre-flight
npm run typecheck✓npm test✓ (1919 pass / 0 fail / 2 skipped gated e2e)npm run build✓ (dist/kimi/native-mcp.js+dist/kimi/bootstrap-hook.jspresent)