Skip to content

feat(v2): land agent-core-v2 engine and kap-server behind experimental flag - #1441

Merged
sailist merged 650 commits into
mainfrom
kimi-code-v2
Jul 12, 2026
Merged

feat(v2): land agent-core-v2 engine and kap-server behind experimental flag#1441
sailist merged 650 commits into
mainfrom
kimi-code-v2

Conversation

@sailist

@sailist sailist commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

N/A — integration PR that lands the long-lived kimi-code-v2 branch; see Problem below.

Problem

The v2 line — the DI × Scope based agent-core-v2 engine, the kap-server that hosts it, and the minidb read model — has been built up on the long-lived kimi-code-v2 integration branch. This PR merges that branch into main.

The v2 engine and server are not the default runtime yet. Both the kimi -p prompt path and kimi server run route to v2 only when KIMI_CODE_EXPERIMENTAL_FLAG is set, and the v2 module graph is lazy-imported so it stays off the default path. With the flag unset, the CLI keeps the v1 engine and @moonshot-ai/server.

What changed

Scope: 1,207 files, +192,653 / −285. The bulk is three new packages; everything else is CLI wiring, e2e coverage, skills, and small v1 touch-ups.

1. agent-core-v2: the new DI × Scope engine (packages/agent-core-v2, +146k, 872 files)

  • New agent-core-v2 package: a DI scope engine with an explicit agent / session lifecycle.
  • Wire/op state engine with derived wire models and ReplayTimelineModel; IEventBus and Op.toEvent alongside wire.signal; context writes routed through ops and declared tool delivery.
  • Per-agent wire records (wire.jsonl); flattened agent hierarchy with swarm lifted to session.
  • Execution environment reorganized into separate filesystem / process / tool domains.
  • Goal mode: core goal workflow, budget enforcement, and per-turn goal injection.
  • Model layer: Model god-object and protocol domains; kosong vendored as the internal llmProtocol/kosong implementation (drops the @moonshot-ai/kosong and @moonshot-ai/kaos dependencies).
  • Built-in tools registered via DI / contributions, plugin management, session subagent host + Agent tool, shared rg locator/runner, AGENTS.md hierarchy loading.

2. kap-server: the v2 server (packages/kap-server, +26k, 139 files)

  • New @moonshot-ai/kap-server package — the Kimi Code server backed by agent-core-v2 (codenamed "server-v2").
  • Hosts agent-core-v2 sessions over REST (/api/v1, ~25 route modules) and WebSocket (/api/v1/ws with seq/epoch watermark and resync), and serves the web assets.
  • Auth and request-security hardening, /openapi.json via @fastify/swagger, and v2 session export (diagnostic zip archives).
  • v1 parity fixes carried along: broadcast interaction question / approval events, honor the before_id pagination cursor, treat loopback origins as same-origin for WS upgrade, and align MCP media output with v1.

3. minidb: embedded read model (packages/minidb, +13k, 77 files)

  • New @moonshot-ai/minidb package — a pure-Node.js embedded KV database (Redis-style in-memory KV with SQLite-style WAL/snapshot persistence, secondary indexes, TTL), used as the session-index read model.

4. CLI wiring (apps/kimi-code, +762, 19 files)

  • kimi -p and kimi server run select v2 vs. v1 via KIMI_CODE_EXPERIMENTAL_FLAG (lazy import); v1 stays the default.
  • Add the v2 harness adapters (cli/v2/*) and the prompt-session abstraction shared by both engines; update TUI adapters to handle v2 events.

5. Tooling, e2e and docs

  • packages/server-e2e: typed v2 ServerClient SDK with a drift test and e2e coverage.
  • .agents/skills: add the agent-core-dev and write-tests skills plus other skill updates; add the dependency-graph dev viewer.
  • GOAL.md: design doc for the goal-mode feature split.
  • Minor: packages/protocol, packages/acp-adapter, packages/agent-core, packages/server, packages/node-sdk, apps/kimi-web, the hash-imports build loaders, flake.nix, and changesets.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

@changeset-bot

changeset-bot Bot commented Jul 6, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 58dde0b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 7 packages
Name Type
@moonshot-ai/kimi-code Minor
@moonshot-ai/agent-core-v2 Minor
@moonshot-ai/protocol Minor
@moonshot-ai/kap-server Patch
@moonshot-ai/klient Patch
@moonshot-ai/agent-core Patch
@moonshot-ai/server Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fbb4a3a0c6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +239 to +240
const session = this.opts.core.accessor.get(ISessionLifecycleService).get(sessionId);
if (session === undefined) return undefined;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Resume cold sessions before accepting WS subscriptions

When a client reconnects to a session that exists only on disk, such as after a server-v2 restart, the default snapshot path can succeed via the disk reader without materializing the session in ISessionLifecycleService. The following /api/v1/ws subscribe then calls ensureState, but this get() only checks live sessions and returns undefined, so the subscribe ack reports not_found and the socket is never registered; if a later prompt request resumes the session, that client still receives no live turn events. Use resume() here or otherwise create a broadcaster state for cold persisted sessions before returning false.

Useful? React with 👍 / 👎.

Comment on lines +1011 to +1015
'file.not_found',
'file.too_large',
'fs.path_not_found',
'fs.permission_denied',
'validation.failed',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the Kimi error schema exhaustive

The KimiErrorCode union above includes additional codes such as prompt.not_found, session.busy, fs.path_escapes, fs.is_directory, fs.is_binary, fs.too_large, fs.already_exists, fs.too_many_results, fs.grep_timeout, and fs.git_unavailable, but this runtime z.enum omits them. Any error or turn.ended.error payload carrying one of those valid codes from agent-core-v2 will fail eventSchema / sessionEventMessageSchema validation even though the TypeScript type says it is valid, so add the missing literals or derive the schema from a single source.

Useful? React with 👍 / 👎.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

❌ Nix build failed

    kimi-code>     at unwrapBindingResult (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/error-CkdMJ9ps.mjs:18:128)
    kimi-code>     at #build (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/rolldown-build-BVD3dIdE.mjs:3275:34)
    kimi-code>     at async build (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/index.mjs:42:22)
    kimi-code>     at async Promise.all (index 0)
    kimi-code>     at async buildSingle (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__2dff369d73d73b1241cfceadc178aa6b/node_modules/tsdown/dist/build-5FURNVr0.mjs:765:19)
    kimi-code>     at async Promise.all (index 0)
    kimi-code>     at async buildWithConfigs (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__2dff369d73d73b1241cfceadc178aa6b/node_modules/tsdown/dist/build-5FURNVr0.mjs:721:18)
    kimi-code>     at async CAC.<anonymous> (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__2dff369d73d73b1241cfceadc178aa6b/node_modules/tsdown/dist/run.mjs:22:2)
    kimi-code>     at async runCLI (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__2dff369d73d73b1241cfceadc178aa6b/node_modules/tsdown/dist/run.mjs:46:3)
    kimi-code> Command failed: /nix/store/chsxa1iw7s3m51v4kj43yd1nw26xvi21-nodejs-24.15.0/bin/node /build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__2dff369d73d73b1241cfceadc178aa6b/node_modules/tsdown/dist/run.mjs --config tsdown.native.config.ts
    kimi-code> 
    kimi-code>  ERROR  Error: Build failed with 2 errors:
    kimi-code> 
    kimi-code> [MISSING_EXPORT] "KimiError" is not exported by "../../packages/agent-core-v2/src/errors.ts".
    kimi-code>     ╭─[ ../../packages/agent-core-v2/src/app/plugin/manager.ts:12:10 ]
    kimi-code>     │
    kimi-code>  12 │ import { KimiError, PluginErrors } from '#/errors';
    kimi-code>     │          ────┬────
    kimi-code>     │              ╰────── Missing export
    kimi-code>     │
    kimi-code>     │ Note: If you meant to import a type rather than a value, make sure to add the `type` modifier (e.g. `import { type Foo } from '#/errors'`).
    kimi-code> ────╯
    kimi-code> 
    kimi-code> [MISSING_EXPORT] "KimiError" is not exported by "../../packages/agent-core-v2/src/errors.ts".
    kimi-code>     ╭─[ ../../packages/agent-core-v2/src/app/plugin/pluginService.ts:17:10 ]
    kimi-code>     │
    kimi-code>  17 │ import { KimiError, PluginErrors } from '#/errors';
    kimi-code>     │          ────┬────
    kimi-code>     │              ╰────── Missing export
    kimi-code>     │
    kimi-code>     │ Note: If you meant to import a type rather than a value, make sure to add the `type` modifier (e.g. `import { type Foo } from '#/errors'`).
    kimi-code> ────╯
    kimi-code> 
    kimi-code>     at aggregateBindingErrorsIntoJsError (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/error-CkdMJ9ps.mjs:48:18)
    kimi-code>     at unwrapBindingResult (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/error-CkdMJ9ps.mjs:18:128)
    kimi-code>     at #build (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/rolldown-build-BVD3dIdE.mjs:3275:34)
    kimi-code>     at async build (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/index.mjs:42:22)
    kimi-code>     at async Promise.all (index 0)
    kimi-code>     at async buildSingle (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__2dff369d73d73b1241cfceadc178aa6b/node_modules/tsdown/dist/build-5FURNVr0.mjs:765:19)
    kimi-code>     at async Promise.all (index 0)
    kimi-code>     at async buildWithConfigs (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__2dff369d73d73b1241cfceadc178aa6b/node_modules/tsdown/dist/build-5FURNVr0.mjs:721:18)
    kimi-code>     at async CAC.<anonymous> (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__2dff369d73d73b1241cfceadc178aa6b/node_modules/tsdown/dist/run.mjs:22:2)
    kimi-code>     at async runCLI (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__2dff369d73d73b1241cfceadc178aa6b/node_modules/tsdown/dist/run.mjs:46:3)
    kimi-code> 
    kimi-code> 
    kimi-code> /build/source/apps/kimi-code:
    kimi-code>  ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  @moonshot-ai/kimi-code@0.23.5 build:native:sea: `node scripts/native/build.mjs --profile=local`
    kimi-code> Exit status 1
    error: Cannot build '/nix/store/z73iav4ji97q4267adr0spq2spcavxcb-kimi-code-0.23.5.drv'.
           Reason: builder failed with exit code 1.
           Output paths:
             /nix/store/gmsbi5i3fybcrnnlc0pc1ff9gpij84kh-kimi-code-0.23.5
           Last 25 log lines:
           > [MISSING_EXPORT] "KimiError" is not exported by "../../packages/agent-core-v2/src/errors.ts".
           >     ╭─[ ../../packages/agent-core-v2/src/app/plugin/pluginService.ts:17:10 ]
           >     │
           >  17 │ import { KimiError, PluginErrors } from '#/errors';
           >     │          ────┬────
           >     │              ╰────── Missing export
           >     │
           >     │ Note: If you meant to import a type rather than a value, make sure to add the `type` modifier (e.g. `import { type Foo } from '#/errors'`).
           > ────╯
           >
           >     at aggregateBindingErrorsIntoJsError (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/error-CkdMJ9ps.mjs:48:18)
           >     at unwrapBindingResult (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/error-CkdMJ9ps.mjs:18:128)
           >     at #build (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/shared/rolldown-build-BVD3dIdE.mjs:3275:34)
           >     at async build (file:///build/source/node_modules/.pnpm/rolldown@1.0.1/node_modules/rolldown/dist/index.mjs:42:22)
           >     at async Promise.all (index 0)
           >     at async buildSingle (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__2dff369d73d73b1241cfceadc178aa6b/node_modules/tsdown/dist/build-5FURNVr0.mjs:765:19)
           >     at async Promise.all (index 0)
           >     at async buildWithConfigs (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__2dff369d73d73b1241cfceadc178aa6b/node_modules/tsdown/dist/build-5FURNVr0.mjs:721:18)
           >     at async CAC.<anonymous> (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__2dff369d73d73b1241cfceadc178aa6b/node_modules/tsdown/dist/run.mjs:22:2)
           >     at async runCLI (file:///build/source/node_modules/.pnpm/tsdown@0.22.0_@arethetypeswrong+core@0.18.2_publint@0.3.18_tsx@4.21.0_typescript@6.0.2__2dff369d73d73b1241cfceadc178aa6b/node_modules/tsdown/dist/run.mjs:46:3)
           >
           >
           > /build/source/apps/kimi-code:
           >  ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  @moonshot-ai/kimi-code@0.23.5 build:native:sea: `node scripts/native/build.mjs --profile=local`
           > Exit status 1
           For full logs, run:
             nix log /nix/store/z73iav4ji97q4267adr0spq2spcavxcb-kimi-code-0.23.5.drv

@pkg-pr-new

pkg-pr-new Bot commented Jul 7, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@58dde0b
npx https://pkg.pr.new/@moonshot-ai/kimi-code@58dde0b

commit: 58dde0b

@sailist sailist changed the title feat(v2): land agent-core-v2 engine and server-v2 feat(v2): land agent-core-v2 engine and kap-server behind experimental flag Jul 8, 2026
kermanx and others added 25 commits July 8, 2026 15:57
- port probeLoginShellPath/mergeLoginShellPath/applyLoginShellPath into
  _base/execEnv/loginShellPath.ts as a pure helper (no DI)
- export execFileText from environmentProbe for reuse by the probe
- run applyLoginShellPathFromNode concurrently with the host probe in
  HostEnvironmentService, mirroring kaos LocalKaos.create()

Aligns agent-core-v2 with kaos 021786f so the Bash tool finds
user-installed tools (e.g. Homebrew's gh) when kimi-code is launched
from a GUI or non-login shell.
- protocol: add optional agent_filter to client_hello and subscribe
- kap-server: carry per-subscription agent allowlists through the broadcaster
  and connection, narrowing live fan-out and replay to selected agents while
  keeping a single global sequence and bypassing the filter for global events
- agent-core-v2: degrade MiniDbQueryStore to a no-op read model when the
  query-store lock is held by another process instead of crashing the host
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
sailist and others added 26 commits July 11, 2026 22:34
…models

- GET /api/v1/models now awaits refreshProviderModels({ scope: 'all' })
  before returning the model list, so the response always reflects the
  latest provider model metadata
- refresh failures are logged and swallowed, falling back to the
  persisted catalog instead of failing the request
Replace fire-and-forget OrderedHookSlot hooks with Emitter/Event-based
notifications for consumers that only observe, never intercept:

- usage: hooks.onDidRecord -> onDidRecord event
- permissionMode: hooks.onDidChangeMode -> onDidChangeMode event
- fullCompaction: hooks.onDidFinishCompaction -> onDidFinishCompaction event
- wireRecord: hooks.onDidFinishResume -> onDidFinishResume event
- agentLifecycle: hooks.onDidStopAgentTask -> onDidStopAgentTask event,
  announced via new notifyAgentTaskStopped() called by mirrorAgentRun

Interception-capable slots (onWillStartAgentTask, onWillCompact,
onDidRestoreRecord) stay as ordered hooks.
… when logged in

When the managed Kimi provider has an oauth ref, WebFetchService builds a MoonshotFetchURLProvider (bearer token + host identity headers) with the local fetcher as fallback, re-reading login state on every call; logged-out setups keep the local fetcher.
…ests

WebSearchProviderService now passes the host's IHostRequestHeaders (User-Agent + X-Msh-* device identity) as default headers to the Moonshot search provider, mirroring v1's kimiRequestHeaders.
The v2 boot path (kimi server run with the experimental flag) now seeds the CLI's Kimi identity headers (User-Agent + X-Msh-* device identity) into the engine through kap-server's seeds option, so outbound model, WebSearch, and FetchURL requests carry the same identity as direct CLI runs. kap-server's own package version is 0.0.0, so the identity has to come from the CLI.
- task: idle terminal notifications now use activeOrNewTurn admission,
  launching their own turn instead of waiting for the next user prompt
  (matches v1 turn.steer)
- workspaceRegistry: createOrTouch rejects missing or non-directory roots
  with fs.path_not_found, so a phantom cwd never reaches session creation
- kap-server: map FS_PATH_NOT_FOUND to protocol error 40409 on the session
  and RPC surfaces
- server-e2e: migrate the v2 smoke test from the local ServerClient to the
  typed Klient
- misc: switch loop/prompt clear() iteration to .slice(), align terminal
  event handler names, and tidy klient examples
The v1 WS broadcaster only re-emitted event.session.status_changed(running)
on turn.started and never emitted the idle/aborted transition on turn.ended.
kimi-web treats that event as the single source of session status (its
turn.ended projector deliberately does not synthesize idle), so a session
stuck at 'running' after the turn finished — most visibly for background
tasks, where ISessionActivity keeps reporting non-idle while the detached
task lives and even a REST pull never corrected it.

Re-emit event.session.status_changed after turn.ended on the same dispatch
queue, mapping reason cancelled/failed/blocked to aborted and otherwise
idle (previous_status 'running'), matching v1's _computeStatus. Update the
broadcaster tests and harden the wsV1Resync test helper so non-matching
frames no longer strand a waiter's timeout.
- listen messages accept a service name; kap-server resolves the Service
  via resolveService and subscribes through its onUpperCase member
- add listen_result acknowledgement and per-listen error reporting
  (onDidListenError) so failed subscriptions surface to the client
- support onWill-style events: payload carries eventId/signal/waitUntil,
  the client replies with event_result and the server can event_cancel
- klient proxy maps onUpperCase members to channel.listen; WsChannel
  shares one remote subscription across first/last listeners
- channel.call now forwards the complete argument array
- register business telemetry events with compile-time property contracts
- redact sensitive values and reject invalid cloud properties
- centralize cloud appender construction and version context
- add describeChannels() to channelRegistry: scope derived from the scoped
  DI registry, public methods/getters enumerated from the prototype chain
  (framework plumbing and events excluded)
- export ChannelDescriptor / ChannelMethodDescriptor from the contract
- serve GET /api/v2/channels so clients (kimi-inspect) can render a
  dynamic service browser without handwritten method lists
- cover with rpc test, e2e channel registry test, and API surface snapshot
- add `params` field to ChannelMethodDescriptor, parsed from function source
- extract declared parameter list via Function#toString with paren-depth tracking
- cover param introspection in rpc and server-e2e channel registry tests
- run-v2-print: drive turns via IAgentPromptService.enqueue() and
  handle.launched; detect hook-blocked prompts via handle.completion;
  read the LoopRunResult type discriminator in formatNativeTurnFailure
- bootstrap stubs: add clientVersion required by IBootstrapService
- v2-run-print test: mock enqueue, stub IBootstrapService for
  createCloudAppender, add track2 to the telemetry stub
- node-sdk test: cover prompt.completed/aborted/steered in the
  exhaustive event switch
… and wire layers

- add `os.fs.*` codes with `HostFsError` and the `toHostFsError` boundary translator
- add `os.process.*`, `storage.*`, and `wire.*` domains with coded error classes
- register new codes in the protocol `KimiErrorCode` union
- translate raw OS and parse failures into domain codes across services, persistence backends, and kap-server transport
- rename `KimiError` to `Error2` in the v2 base errors
- remove obsolete kimi-csdk init example
The MCP initial-connect assertion used a single setTimeout(0) tick, but
connectAll is gated on Promise.all([resolveSessionMcpConfig(...),
enabledMcpServers()]); the session-config side walks the real filesystem
(project-root search + mcp.json reads), which does not settle within one
macrotask under CI load. Use vi.waitFor so the test is robust on CI.
In valueMode 'disk' the write path installed a disk ValueLoc using the
predicted WAL offset before the frame's bytes were flushed (appendLoc
returns the offset synchronously; the writev lands on a later tick). Under
load a concurrent compaction snapshot could read a pointer past the WAL end
and fail with a short read. Apply the record as an in-memory ref first and
only publish the disk pointer after appended.done resolves, guarded against
WAL rotation and stale record seqs.
- resolveScope now throws Error2 for missing session/agent instead of
  returning undefined, distinguishing agent.not_found from session.not_found
- map AGENT_NOT_FOUND onto the session-not-found protocol envelope for v1
  parity
- remove KIMI_PRINT_V2_ENV / isPrintV2Enabled and the dedicated
  KIMI_CODE_EXPERIMENT_FLAG switch
- route `kimi -p` to the agent-core-v2 runner via isKimiV2Enabled,
  the same master switch that gates server-v2
- unwrap the HostFsError cause before matching EISDIR in FileEditService,
  restoring the "is not a file" edit output broken by the error taxonomy
- map os.fs.* codes to the closest v1 wire codes in the kap-server fs
  route and /api/v2 transport instead of collapsing to INTERNAL_ERROR
- map storage.io_failed / storage.locked to PERSISTENCE_FAILURE in the
  /api/v2 transport
A User-target set/replace mutates raw/rawSnake, awaits persist(), then
rebuilds effective, while a reload() replaces all three wholesale from disk.
Without serialization a reload whose file read resolves inside a write's
persist window (before the atomic rename lands) restores the stale pre-write
state, so the write's post-persist rebuild drops the just-written domain from
effective. This surfaced as POST /config responses missing the field they had
just written when the startup model-catalog refresh's reload() raced the
write. Run User-target writes and reloads through a promise chain so they can
no longer interleave.
- rename tool_call_dedupe_detected to tool_call_dedup_detected
- emit turn_ended on every turn end; add mode/provider/protocol tags
  and interrupt_reason to turn_started/turn_interrupted
- enrich api_error with alias, protocol tags, and input_tokens
- tag tool_call with dup_type via an executor-side map (avoids the
  executor/dedupe DI cycle)
- rename compaction usage fields to input_tokens/output_tokens
- add context_projection_repaired, session_started, and
  session_load_failed events
- add guarded synchronous and asynchronous state transitions
- support commit, rollback, cleanup, and compensation actions
- cover transition conflicts, action ordering, and failure aggregation
- Degrade plugin consumption reads to empty when installed.json fails to
  load, surface plugin.load_failed with a repair hint on management calls,
  and recover after an explicit reload; serialize the initial load and
  mutations so concurrent first callers share one load.
- Clean up zip temp dirs on every failure path, report the original
  source in zip/github manifest errors, and roll back to the previous
  managed copy when an install or persist fails.
- Restore managed Kimi endpoint env injection for stdio plugin MCP
  servers.
- Check plugin updates concurrently with per-repo failure isolation and
  10s timeouts, track branch installs by commit SHA, and stop false
  update reports for tag/SHA pins.
- Throw plugin.not_found from getPluginInfo and the manager's
  not-installed paths.
- Count plugin skills through the real skill discovery path.
- Re-sync context injection positions after silent wire replay so cold
  resumes do not duplicate injections, and fire plugin session-start
  reminders only when the plugin skill source finishes refreshing.
- keep model catalog reads free of provider refresh side effects
- broadcast deduplicated session lifecycle and interaction statuses
- cover catalog loops and global session status fan-out
@sailist
sailist merged commit ceb158d into main Jul 12, 2026
10 checks passed
@sailist
sailist deleted the kimi-code-v2 branch July 12, 2026 13:44
@github-actions github-actions Bot mentioned this pull request Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants