feat(v2): land agent-core-v2 engine and kap-server behind experimental flag#1441
feat(v2): land agent-core-v2 engine and kap-server behind experimental flag#1441sailist wants to merge 556 commits into
Conversation
- handle `kimi v2 <subcommand>` in main.ts, gated on KIMI_CODE_EXPERIMENTAL_FLAG via shared isKimiV2Enabled - route `kimi server run` to server-v2 through the same switch; drop server-v2 standalone main.ts/dev script - fold v1 context.append_loop_event records into messages at replay and snapshot so v1 sessions restore on agent-core-v2 - report backend: 'v2' in meta; serve session status via SessionLegacyService.status - drop unused service options (blob/fullCompaction/goal/permissionGate); permissionGate reads agentId from scope context
…gistration
AgentBlobServiceImpl no longer takes constructor arguments, so remove the
now-unnecessary [{}] from its SyncDescriptor registrations in the agent
lifecycle service and the blob tests.
🦋 Changeset detectedLatest commit: 9f1827e The changes in this PR will be included in the next version bump. This PR includes changesets to release 6 packages
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 |
There was a problem hiding this comment.
💡 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".
| const session = this.opts.core.accessor.get(ISessionLifecycleService).get(sessionId); | ||
| if (session === undefined) return undefined; |
There was a problem hiding this comment.
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 👍 / 👎.
| 'file.not_found', | ||
| 'file.too_large', | ||
| 'fs.path_not_found', | ||
| 'fs.permission_denied', | ||
| 'validation.failed', |
There was a problem hiding this comment.
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 👍 / 👎.
# Conflicts: # apps/kimi-web/src/api/daemon/agentEventProjector.ts
|
❌ Nix build failed Hash mismatch in
Please update |
- introduce ModelBlobCodec ({ dehydrate, rehydrate }) declared on ModelDef.blobs; the model owns record/state traversal, WireService owns storage I/O
- remove WireBlobSelector / WireBlobTarget and the contextBlobSelector seed; declare blob handling inline on ContextModel.blobs
- rename IAgentBlobService.rehydrateParts -> loadParts and PartsRehydrator -> PartsTransformer (same shape for both directions)
- WireService.appendToWireLog routes dehydrate through the per-record model codec instead of a construction-time selector
- derive session title and lastPrompt from the first prompt before the turn launches, then broadcast session.meta.updated on IEventService so the web title updates live - generalize the prompt metadata update to cover prompt() and activateSkill(), not just plugin commands - add turn.started origin and new prompt/session/fs error codes to the protocol schema - rename the background.task_id_empty error code to task.task_id_empty
- add scripts/debarrel.mjs (ts-morph) to rewrite #/<dir> imports to precise leaf specifiers and regenerate src/index.ts - rewrite src and test consumers across the package to import from leaf files instead of domain barrels - delete src/app/event/index.ts barrel and load its leaves from the package entry - extract applyPromptMetadataUpdate so /api/v1 prompt submission derives the easy session title, matching /api/v2 - rename the v2 prefix to beta in the CLI prefix tests
…into kimi-code-v2
When the Kimi OAuth toolkit short-circuits via its `ensureFresh` fast path (the cached refresh token is still usable), `toolkit.login` resolves without firing `onDeviceCode`. The v2 `OAuthService.startLogin` previously rejected in this case, so `POST /api/v1/oauth/login` returned a 500 that the web client swallowed and mislabeled as "current daemon does not support login". CLI-authenticated users could not (re)enter the v2 daemon through the web UI. Treat that path as already authenticated: provision the managed provider (idempotent), refresh OAuth provider models so `defaultModel` is seeded (`/auth` then reports ready, matching v1 parity), and return a new `status: 'authenticated'` `OAuthFlowStart` variant so the web LoginDialog can skip the device-code UI entirely instead of falling into its catch-all "unsupported daemon" state. The protocol `OAuthFlowStart` schema is now a discriminated union on `status`; kimi-web's wire / composable / LoginDialog types are updated to handle the new `authenticated` branch. Tests: updated the v2 OAuthService test that previously asserted the buggy rejection to instead assert the fast path returns authenticated and provisions the provider.
…into kimi-code-v2
Move MicroCompactionEffect next to the service that produces it, and derive MicroCompactionConfig from the single zod schema in configSection.ts so the section schema and the runtime config type no longer drift.
Run SubagentStart/SubagentStop and SessionStart/SessionEnd external hooks by observing hook slots instead of being invoked directly, matching the other external-hook observers. - Add Agent-scoped IAgentRunHooksService hosting onWillStartAgentTask / onDidStopAgentTask; mirrorAgentRun runs those slots rather than calling IAgentExternalHooksService directly. - AgentExternalHooksService registers on those slots to emit SubagentStart/SubagentStop; drop runAgentTaskStart/notifyAgentTaskStop from its public interface. - Add Session-scoped ISessionExternalHooksService. ISessionLifecycleService gains onDidCreateSession / onWillCloseSession slots announcing source/reason for create, resume, fork, close, archive. - Move externalHooks from L5 to L6 in check-domain-layers.mjs, update the DI dependency map, and drop now-dead Hooks/OrderedHookSlot/@IAgentTurnService imports.
…fresh OAuthService.invalidateFlows previously cleared every in-flight device-code login on any provider config change. Startup-time model catalog refreshes rewrite the providers section without changing the OAuth provider itself, which aborted the active login and left the web login dialog stuck polling an empty flow after the user authorized in the browser. Scope invalidation to providers that were removed or had their config changed, so an in-flight login for an unaffected provider completes normally.
Context injections can now return either plain reminder text or pre-built content parts, with turn-boundary state exposed to providers instead of the cadence option.
…into kimi-code-v2
Replace the standalone HookEngine class with an App-scope IExternalHooksRunnerService that owns loading (config + plugin.enabledHooks()) and matching/running hooks. The Agent- and Session-scope external-hooks adapters now just observe their hook slots and inject the shared runner, so the duplicated per-adapter engine lifecycle (loadDynamicHooks / reload / ready gating / plugin.onDidReload) goes away. - Add src/app/externalHooksRunner/ with the contract, App-scope impl, and a pure runner module (indexHooks / runMatchedHooks / blockDecision). - Drop public HookEngine, HookEngineTriggerArgs, HookEngineOptions, and the ExternalHooksServiceOptions escape hatch; move HookEngine run/match logic into the runner. - Register externalHooksRunner at L6 and export it from the package index. - Migrate tests to a real runner built by makeHookRunner() and the externalHookServices() harness override; split engine.test.ts traits into externalHookRunner.test.ts.
IAgentContextSizeService.getStatus() becomes get(start?, end?) returning { size, measured, estimated } where size = measured + estimated. start/end follow Array.prototype.slice semantics (default whole context, negative indices count from the end, inverted range is empty). Update consumers, the context:status action binding, tests, and the edge-exposure cheatsheet.
- add optional `stack` field to errEnvelope and the envelope schema/interface; omitted when undefined so the wire shape stays byte-identical for callers without a stack - thread `err.stack` through route error mappers plus the global and transport error handlers - preserve `details` on `session.undo_unavailable` while adding its stack - update tests to assert stacks are surfaced, reversing the prior no-leak contract
…into kimi-code-v2
* feat(agent-core-v2): record shell command context - add ShellCommandOrigin and compaction handoff disposition - extract IAgentShellCommandService from AgentRPCService - keep AgentRPCService as a thin shell:run facade * fix(agent-core-v2): align skill priority and sync docs - restore project > user > plugin > builtin skill precedence - sync Skill tool description and parameter docs from v1 - update write-goal and custom-theme builtin skill copy * fix(agent-core-v2): restore undo and thinking telemetry - track conversation_undo after undoHistory - emit thinking_toggle with enabled/effort/from payload - add coverage for both telemetry events * feat(agent-core-v2): add skill directory config - add extraSkillDirs and mergeAllAvailableSkills config sections - introduce extra skill source and shared source priorities - align kap-server workspace skill preview with session catalog * feat(agent-core-v2): support explicit skill dirs - add ISkillCatalogRuntimeOptions for SDK-style explicit skill dirs - suppress default user/project discovery when explicitDirs are set - resolve explicit dirs per session workDir via explicitFileSkillSource * fix(agent-core-v2): fix configured skill dir resolution - expand ~ using OS home for configured skill dirs - honor explicitDirs in kap-server workspace skill preview * fix(agent-core-v2): await config ready before skill discovery - wait for config.ready before reading extraSkillDirs - wait for config.ready before reading mergeAllAvailableSkills - cover extra skill dir loading behind config readiness * fix(agent-core-v2): keep skill config live after changes - await config.ready in kap-server workspace skill preview - reload user and workspace skill sources when mergeAllAvailableSkills changes
…into kimi-code-v2
- add `activity` domain: `IAgentActivityService` (Agent turn lane machine), `ISessionActivityKernel` (Session admission, PR1 placeholder), and the `ActivityLease` that owns the turn `AbortSignal` - turnService launches and cancels through the kernel lease; `Turn` now exposes `signal` instead of `abortController` - agentLifecycle.remove drives `beginDisposal`/`settled` and waits for the in-flight turn to drain before releasing the agent scope - add `activity.*` error codes; deprecate `turn.agent_busy` in favor of `activity.agent_busy`
These four legacy session actions were thin delegations to the native v2 services (ISessionLifecycleService.fork/archive, IAgentFullCompactionService.begin, IAgentRPCService.cancel) with no v1-only projection to centralize. Drop them from ISessionLegacyService and call the native services directly from the kap-server sessions route. updateProfile, createChild, listChildren, undo and status stay in the adapter since they carry real v1 adaptation logic.
- add native v2 print runner (v2/run-v2-print.ts) that consumes agent-core-v2 DI services and awaits Turn.result directly - extract shared print-mode rendering into prompt-render.ts for v1 and v2 - remove the V2PromptHarness/V2Session shim and v2->v1 event translation - decouple initializeCliTelemetry from PromptHarness (homeDir/auth/track) - add IAgentPromptLegacyService.submitAndSettle for authoritative completion
- make IAgentPromptService.undo throw session.undo_unavailable with a structured
reason; move the precheck into contextMemory
- add ISessionLifecycleService.createChild (fork + child markers) and
ISessionIndex.list({ childOf })
- slim ISessionLegacyService to updateProfile/status (drop createChild,
listChildren, undo)
- rewire kap-server session routes to the native services and map
SESSION_UNDO_UNAVAILABLE
- run-v2-print: use core ITelemetryService + CloudAppender instead of kimi-telemetry; remove kimi-code-sdk import (auth via IOAuthToolkit, config path from bootstrap, hook result via structural type) - prompt-render: replace SDK HookResultEvent with a structural type so the shared renderer does not depend on the v1 SDK event shape - telemetry: revert initializeCliTelemetry to its original signature now that v2 no longer calls it; keep v1 callers and assertions untouched - update run-prompt and v2-run-print tests for the new wiring
- implement SessionActivityKernel lane machine (restoring→active⇄quiescing→closing→disposed) with admission table, atomic quiesce+drain, beginClosing/settled, markActive - start AgentActivityService lane at initializing; add markReady driven by agentLifecycle.create after bootstrap - project LaneModel + EventBus facts into structured AgentActivitySnapshot (ActivityModel / setActivitySnapshot Op) with pending-approval and active-tool-call sets; emit agent.activity.updated - add IAgentTurnService.launchWithLease; goal continuation acquires the lane before appending its prompt - resolve pending interactions on turn.ended to avoid stranded awaiting_approval - fullCompaction registers a background activity and checks the activity lane - extract contextMemory publishSplice / isFullyUndoable / recoverFoldedLength helpers - kap-server: map activity snapshot into legacy status and sessionEventBroadcaster
…into kimi-code-v2
…into kimi-code-v2
…into kimi-code-v2
Related Issue
N/A — integration PR that lands the long-lived
kimi-code-v2branch; see Problem below.Problem
The v2 line — the DI × Scope based
agent-core-v2engine, thekap-serverthat hosts it, and theminidbread model — has been built up on the long-livedkimi-code-v2integration branch. This PR merges that branch intomain.The v2 engine and server are not the default runtime yet. Both the
kimi -pprompt path andkimi server runroute to v2 only whenKIMI_CODE_EXPERIMENTAL_FLAGis 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)agent-core-v2package: a DI scope engine with an explicit agent / session lifecycle.ReplayTimelineModel;IEventBusandOp.toEventalongsidewire.signal; context writes routed through ops and declared tool delivery.wire.jsonl); flattened agent hierarchy with swarm lifted to session.Modelgod-object and protocol domains; kosong vendored as the internalllmProtocol/kosongimplementation (drops the@moonshot-ai/kosongand@moonshot-ai/kaosdependencies).rglocator/runner, AGENTS.md hierarchy loading.2. kap-server: the v2 server (
packages/kap-server, +26k, 139 files)@moonshot-ai/kap-serverpackage — the Kimi Code server backed byagent-core-v2(codenamed "server-v2").agent-core-v2sessions over REST (/api/v1, ~25 route modules) and WebSocket (/api/v1/wswith seq/epoch watermark and resync), and serves the web assets./openapi.jsonvia@fastify/swagger, and v2 session export (diagnostic zip archives).before_idpagination 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)@moonshot-ai/minidbpackage — 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 -pandkimi server runselect v2 vs. v1 viaKIMI_CODE_EXPERIMENTAL_FLAG(lazy import); v1 stays the default.cli/v2/*) and theprompt-sessionabstraction shared by both engines; update TUI adapters to handle v2 events.5. Tooling, e2e and docs
packages/server-e2e: typed v2ServerClientSDK with a drift test and e2e coverage..agents/skills: add theagent-core-devandwrite-testsskills plus other skill updates; add the dependency-graph dev viewer.GOAL.md: design doc for the goal-mode feature split.packages/protocol,packages/acp-adapter,packages/agent-core,packages/server,packages/node-sdk,apps/kimi-web, thehash-importsbuild loaders,flake.nix, and changesets.Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.