mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-07 15:56:39 +00:00
* feat(minidb): instrument open lifecycle with phase timings and status Add MiniDb.lifecycleStatus() exposing the no-generation/generation-load/ wal-catch-up/full-rebuild/ready/degraded state machine plus per-phase timings (generation candidate load, store/non-text/text image load, postings integrity check, WAL scan/apply, full recovery, text rebuild hosting), so snapshot load, WAL catch-up and full rebuild can be told apart in diagnostics. Also add a repeatable open-lifecycle bench (small data, large WAL delta, large full-text generation, corrupt generation) and fixtures proving a healthy generation open performs no full-corpus tokenization while a corrupt or missing generation falls back. Log search-index and query-store open diagnostics in kap-server and agent-core-v2 so a listSessions call can be attributed to the database it touches. No persistence format or product behavior change. * feat(agent-core-v2): isolate the session index from the global search index Harden the separation between the session read model and the full-text search index so session operations never depend on search availability: - Reject text index definitions in MiniDbQueryStore at definition level, keeping the session query-store a structural-only read model with no postings/tokenizer artifacts, and assert its generation carries no full-text files. - Share one authoritative scan between the first list and the initial projection (single-flight) instead of scanning twice; reads may only join an in-flight scan, and every fallback read folds the mirror's pending queue so read-your-writes holds while preparing. - Keep withReadModel() fallback semantics pinned by tests: uninitialized/preparing reads hit authoritative metadata immediately, ready reads use the read model, degraded keeps falling back with a diagnosable status reason. - Guard session metadata writes so a mirror failure degrades only the read model and never fails the session lifecycle. - Prove via tests that listSessions/--resume/--continue never open the global search DB (including when search-index is unopenable), and that only real full-text search requests report building/stale/degraded. * perf(minidb): slice open-time work so it never blocks the main thread Make the whole generation-open path cooperative: - Replace the synchronous postings/store CRC verification with chunked async variants (readGenerationFileCheckedAsync, verifyFileIntegrityAsync) that keep the exact bytes/crc-mismatch error semantics. - Give the WAL-delta apply a primitive-op + wall-clock budget (walApplySlicer), so a batch frame unrolling into thousands of ops can no longer run as one uninterruptible slice; torn-tail, corrupt-batch and read-only behaviors are unchanged. - Slice the big attach loops: Store.bulkLoadRefsAsync + SkipList.bulkLoadAsync for the store image, async parsers and loadImageAsync for secondary/compound images, and TextIndex.attachImageAsync for the docs/dictionary map construction. - Queue text builds on worker-slot pressure (WorkerSlots.acquireBounded, bounded by MiniDb.textBuildSlotWaitMs, abort-aware) instead of falling back to an unbounded inline build; a persisted drought hosts the bounded inline core as the explicit last resort with stats accounting. Bench (bench/open-lifecycle, seed 42): event-loop delay max across the four open scenarios drops from 45/734/331/492 ms to ~12-28 ms with wall time flat or better. * feat(kap-server): run the global search index in a dedicated worker Move the whole search-index MiniDb lifecycle (open, generation load, WAL replay, sync, rebuild, compaction) off the main thread into a long-lived worker_threads host, so it never shares the event loop with TUI input: - Add a versioned request/response protocol and worker entry hosting a host-agnostic SearchIndexCore; the same core also backs an inline backend kept as the explicit rollback (KIMI_CODE_EXPERIMENTAL_SEARCH_WORKER=false, flag default ON). - The worker exclusively owns the search-index handle. The lock token is reported at acquire time (new MiniDb OpenOptions.onLockAcquired hook) and reaped on dirty exit; an orphan-lock detector (same-pid lock row whose token no live holder owns) recovers the window where the token report is lost, so a mid-open crash can never freeze the index into a silent permanent read-only. - Crash handling: in-flight requests are rejected with typed errors, respawn uses capped exponential backoff, per-request watchdogs terminate wedged workers, and beginClose propagates into the worker so dispose stays bounded during a long sync. Page tokens pin a boot-salted generation, so tokens issued before a transparent worker restart fail closed with invalid_page_token. - The main process keeps the sync coordinator (debounce/coalescing/ single-flight), live transcript routing, query normalization and page-token codec; searches keep reading the published generation and report building/stale/degraded instead of waiting for sync/rebuild. - Wire the worker into the CLI packaging: self-contained worker bundles for npm dist and the SEA asset manifest/installer/smoke check, plus a dev runtime (type-stripping + .ts resolve hook) scoped to worker execArgv. * feat(kap-server): model search and session-index lifecycles explicitly Consolidate the two-index separation into explicit, diagnosable lifecycles: - Surface the global search state machine (stopped / opening / building / ready / degraded / closing) end to end: SearchIndexCore.lifecycleState, SearchWorkerHost lifecycle snapshots cached from RPC responses (and invalidated across worker generations), a never-throwing status() carrying the lifecycle, and a synchronous lifecycleReport() that neither kicks the open nor spawns the worker. Corrupt search-index rebuilds are announced with a dedicated warn log so building, stale, degraded, corrupt and worker-unavailable stay distinguishable. - Turn MiniDb read-only replica catch-up fully cooperative: catchUpWalAsync scans frames with the windowed async scanner and yields per primitive op on the shared walApplySlicer budget, while a per-instance catchUpChain serializes concurrent catch-ups so each caller keeps its atomic watermark advance. The stale synchronous implementations are removed. - Pin the dependency direction and availability timing with tests: session list/create/resume survive a corrupt or unopenable search index (also end-to-end with a dead query-store), search generation reuse and stale-serving keep working across restarts, concurrent cold callers open the index / spawn the worker exactly once, resume-then- fetchSessions performs no duplicate authoritative scan, and a clean dispose releases the lock and settles at stopped. - Document the experimental flag surface (persistence_minidb_readmodel, search_worker) in the root guide. * feat(agent-core-v2): default the session read model on and roll out the separation Rollout and validation for the index separation plan: - Flip persistence_minidb_readmodel to default ON (rollback via KIMI_CODE_EXPERIMENTAL_PERSISTENCE_MINIDB_READMODEL=false or the experimental config section); session list/--resume/--continue now always go through the isolated session read model with the authoritative fallback. Test harnesses pin the flag off where shared fixtures require hermetic homes, while the dedicated suites keep explicit on/off coverage. - Add a probe proving the main thread stays responsive while the search worker rebuilds and swaps a generation (reindex), completing the TUI responsiveness matrix. - Record the rollout state in the agent-core-v2 guide (session index section) and the root flag line. - Add changesets for the CLI (worker isolation, session index independence) and minidb (cooperative open lifecycle). Validation: full suites green across minidb (551), agent-core-v2 (4760), kap-server (1005), node-sdk (343), klient (91) and the CLI app (2567); open-lifecycle bench event-loop delay max is down from 45/734/331/492 ms to ~16-22 ms across the four scenarios with wall time flat or better. * fix(agent-core-v2): evict deleted sessions from the mirror queue and drain the index on close Two issues surfaced by the read-model default in the acp-server suite: - ISessionIndex.remove only deleted from the query store, but a summary still queued in the mirror was folded back into reads (and re-written by the next flush), resurrecting a deleted session in listings. The mirror now exposes evict(id): drop the queued summary and wait out an in-flight flush before the store delete. - RunningAcpServer.close and SDKRpcClientV2.close disposed the engine without awaiting the asynchronous mirror flush / query-store close, so a host removing homeDir right after close() raced in-flight shard closes (ENOTEMPTY). Both now follow the kap-server shutdown order: drain the mirror while the store is open, dispose, then await the drains. * fix(minidb): pause active expiry during the sliced bulk load The store's active-expire timer is armed at construction, so during a sliced bulkLoadRefsAsync a tick can fire mid-load: it reaps a TTL key from the map while the order skiplist is still the old empty one, and the final bulkLoadAsync then rebuilds order from the stale orderEntries snapshot — resurrecting the expired key in the ordered index (and duplicating it if the key is later set again). The sync bulkLoadRefs had no yield windows, so guard the async path with a bulkLoading flag that defers expiry ticks until the load settles (finally-safe). * chore: consolidate changesets into the TUI startup freeze fix |
||
|---|---|---|
| .. | ||
| acp-adapter | ||
| acp-server | ||
| agent-core | ||
| agent-core-v2 | ||
| kaos | ||
| kap-server | ||
| klient | ||
| kosong | ||
| migration-legacy | ||
| minidb | ||
| node-sdk | ||
| oauth | ||
| pi-tui | ||
| protocol | ||
| telemetry | ||
| transcript | ||
| tree-sitter-bash | ||