Subagents created via the Agent tool or AgentSwarm fell back to the
default `manual` permission mode because CreateAgentOptions offered no
way to seed one, so write/execute tool calls inside a subagent prompted
for approval even when the parent ran in auto/yolo.
Add an optional permissionMode to CreateAgentOptions and have the Agent
tool and AgentSwarm pass the caller's current mode when creating a
child.
The v2 server package is @moonshot-ai/kap-server, but three changesets still referenced the old @moonshot-ai/server-v2 name, which no longer exists in the workspace.
- bridge split v2 status slices into one combined `agent.status.updated`
event via a LegacyStatus derived model at the kap-server edge, so a
usage-only event no longer overwrites the live context window with a
stale zero
- fall back to the configured default model's context window when the
agent has no model bound yet, so fresh sessions don't show "0/0"
- use `size` (measured + estimated) for the live context token count to
mirror v1's `context.tokenCount`
- export `defineDerivedModel` / `DerivedModelDef` from agent-core-v2
- add a per-connection outbound send buffer in WsConnectionV1; sendFrame
enqueues and a flush drains on a 16ms interval or once 64 frames queue
- coalesce adjacent volatile assistant/thinking deltas for the same
session/agent/turn into one frame, keeping the first offset/seq so
client alignment is unchanged
- defer flushing while socket.bufferedAmount exceeds a 1MiB high-water
mark, merging new deltas into the queued frame instead of growing it
- flush remaining frames on close to avoid truncating the tail of a stream
- expose flushIntervalMs / maxBatchSize / highWaterMarkBytes via registerWsV1
- add PromptHarness/PromptSession interfaces so the print driver is
decoupled from the concrete SDK harness/session
- add an in-process agent-core-v2 harness (bootstrap + session +
prompt/goal/permission adapters) under cli/v2/
- adapt v2 IEventBus events to the v1 Event union, with unit tests
- select the engine in createPromptHarness via isKimiV2Enabled()
(KIMI_CODE_EXPERIMENTAL_FLAG), lazy-importing v2 off the default path
Forward event.session.created to WS clients (it was published on the core
bus but never forwarded) and re-emit event.session.status_changed(running)
on turn.started. v2 derives session status via ISessionActivity, a pure pull
that publishes nothing, so these v1 broadcasts were dropped: clients that
did not issue a create never learned the session existed, and the running
transition never reached kimi-web, whose Stop button is gated on
session.status === 'running'. Mirrors v1's SessionService status emission
and isGlobalSessionEvent fan-out.
server-v2 binds the main agent via profile:setModel without a cwd, so
the profile cwd is empty and planFilePathFor() produced a relative path
like plan/<id>.md. The plan-mode guard compares that against the Write
tool's workDir-resolved absolute path with strict equality, so it denied
every write to the plan file; the relative path also landed in
process.cwd() instead of the session workDir, breaking ExitPlanMode.
Make the plan path always absolute, falling back to the session workDir
(the same root the file tools resolve against) when the profile cwd is
empty.
`resolveLegacy` always resolved the main agent, ignoring `agent_id` in the
prompt submission body. A `/btw <question>` submit carries the forked
side-channel child's `agent_id`, so it was answered in the main view instead
of the right-side BTW panel.
Resolve the agent named by `agent_id` (falling back to `main`), and return
40401 for an unknown agent id. Add regression tests for side-channel routing
and the unknown-agent case.
- gate startServer on KIMI_CODE_EXPERIMENTAL_MULTI_SERVER: register under server/instances/ and rely on port+1 retry for coexistence, or take the legacy single-instance lock when off
- release/update the chosen handle on close, boot refusal, and after bind so the advertised port stays accurate
- export the instance registry API from the package barrel
- fix session.meta.updated to dispatch under the real session id instead of '__global__' so auto-titled and renamed sessions update in clients
- add `multi_server` experimental flag in agent-core-v2 and wire it into the package barrel
- add kap-server instance registry that writes per-server files under server/instances/ with heartbeat and stale-pid sweep
- thread PromptOrigin through AgentTurnService.launch and emit it on turn.started
- drop the error field from cancelled loop/turn results and use userCancellationReason in promptLegacy
- Drop numeric telemetry properties whose absolute value exceeds Number.MAX_SAFE_INTEGER before enqueue, and reject them again during payload assembly as a backstop.
- Omit constrained_memory_bytes when process.constrainedMemory() is not a safe non-negative integer so Linux no-cgroup sentinels do not overflow int64 parsing downstream.
- Add telemetry tests for unsafe numeric properties and constrained_memory_bytes filtering.
- cascade context_size.measured when context memory clears, undoes, compacts, or splices the measured prefix
- add context memory tests for measured prefix reset and rebase behavior
- fix lint issues around task tool side-effect imports, web fetch type cycle, and unused imports
Restore the enforced-requirements paragraph in the AgentSwarm tool description and assert it, cover the AgentSwarm exclusive-deny and swarm-mode-approve permission policies, and add resolveSwarmMaxConcurrency plus AgentRunBatch swarmItem forwarding tests.
The opaque per-key tool store (IAgentToolState / ToolStoreModel / updateStore) had no remaining producer or consumer in v2: its only real user, the todo list, was migrated to the dedicated session/todo domain (ISessionTodoService, TodoModel, todo.set). Drop the domain, its index exports, and the dangling references in kap-server actionMap, server-e2e resources, the test harness, ResumedAgentState, and the DI-scope docs. Replay silently skips the now-unregistered tools.update_store record type.
Reconciled with upstream de-barrel refactor (direct imports, removed per-domain barrels) and the loop-context interface rename. Kept the agent-run hook slot host on IAgentLifecycleService (run by mirrorAgentRun, observed by the Session-scope externalHooks adapter) and dropped the standalone IAgentRunHooksService, resolving conflicts in agentLifecycle, mirrorAgentRun, both externalHooks adapters, and the affected tests.
Move the requester-side agent-run hook slots (onWillStartAgentTask / onDidStopAgentTask) onto IAgentLifecycleService, the service whose run mirrorAgentRun wraps. mirrorAgentRun now resolves IAgentLifecycleService to run the slots, and the Session-scope SessionExternalHooksService observes them to translate into SubagentStart / SubagentStop external hook commands.
This removes the standalone Agent-scope IAgentRunHooksService (runHooks.ts) and the SubagentStart/Stop observation from the Agent-scope AgentExternalHooksService, so the slot host lives on the service that runs the agent task and the external-hooks adapters only observe. ISessionExternalHooksService becomes an empty observer token (it still registers SessionStart/SessionEnd via sessionLifecycle).
Update affected tests, IAgentLifecycleService stubs, and the DI Scope x Domain dependency map (puml + regenerated svg).
- rename packages/server-v2 to packages/kap-server and update every
@moonshot-ai/server-v2 reference across apps, packages, flake.nix,
and build scripts
- remove the experimental `kimi v2` CLI prefix and its tests from the
apps/kimi-code main entry
- add legacy BackgroundTask protocol types and the `blocked` turn
interrupt reason for cross-engine compatibility
* refactor(web): migrate icons to unplugin-icons
Replace the hand-written gen-icon-data.mjs + @iconify/utils runtime
rendering with unplugin-icons build-time imports. The public API
(<Icon name>, iconSvg, IconName, SIZE_PX, NAME_TO_REMIX) is unchanged;
127+ call sites are untouched.
- add unplugin-icons@^23.0.0 (devDep) + Vite Icons() plugin (compiler: vue3)
- rewrite src/lib/icons.ts: static ~icons/ri/* imports (component + ?raw)
for 56 distinct Remix icons across 59 IconName entries
- Icon.vue renders <component :is> with unknown-name fallback
- append ICON_GROUPS export for DesignSystemView catalog
- DesignSystemView: v-for catalog, remove legacy-script references
- delete gen-icon-data.mjs, gen-icon-catalog.mjs, icon-data.ts,
gen:icons script
- remove @iconify/vue and @iconify/utils from dependencies; move
@iconify-json/ri to devDependencies
- drop Icon.vue from check-style ICON_EXEMPT (no hand-written <svg>)
* refactor(web): drop unused NAME_TO_REMIX icon mapping
NAME_TO_REMIX was a Record<IconName, string> table introduced to map
internal icon names to their ri: ids. After the unplugin-icons migration
it has no production consumers — only icons.test.ts imported it (for two
drift tests) and DesignSystemView mentioned it in descriptive copy. The
ICONS table already conveys the same ri: id via each entry's paired
component + ?raw imports (e.g. RiFolderOpenLine / RawFolderOpenLine).
- remove NAME_TO_REMIX const from src/lib/icons.ts (-63 lines)
- remove NAME_TO_REMIX import + describe block from icons.test.ts
- update DesignSystemView §02 copy: describe the import-pair idiom and
stop claiming ICON_GROUPS is sourced from NAME_TO_REMIX
* chore: add changeset for web icon migration
* chore(nix): bump pnpmDeps hash for unplugin-icons
Adding unplugin-icons changed pnpm-lock.yaml, so the fixed-output
pnpmDeps derivation hash is stale. Update to the hash reported by the
Nix Build CI run.
- delete per-directory index.ts barrel files across src/ submodules
- update src and test imports to reference concrete module files directly
- rename a few index.ts entry files to named modules (migration.ts, providers.ts, builtin.ts)
- rewire src/index.ts to export from concrete modules instead of directory barrels
- add patch changeset noting the production-build fix
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.
Pass windowsHide:true when spawning the hook process so a visible console
no longer flashes and steals focus on Windows. The Bash-tool path was
already hardened (KAOS buildLocalSpawnOptions); the hook runner missed the
flag even though its own taskkill helper already set it.
Extract the spawn options into a pure builder and add a regression test
asserting windowsHide, mirroring the existing KAOS spawn-options test.
Relates to #1298.