* fix(migration-legacy): faithfully migrate kimi-cli user data into kimi-code
* fix(migration-legacy): faithfully migrate kimi-cli user data into kimi-code
* fix(vscode): keep current and root work dirs visible in directory picker
* refactor(vscode): migrate the webview data layer from ahooks to TanStack Query
* refactor(vis): migrate vis from agent-core v1 to agent-core-v2
- swap vis-server engine deps to @moonshot-ai/agent-core-v2, drop kosong
- rebuild the wire record union from v2 durable payload types
- fold token_counting records into the context-window fill
- read cron state from wire records alongside legacy cron files
- read agent parent/swarm metadata from state.json labels
- align context projection and web rendering with the v2 wire vocabulary
- bundle agent-core-v2 into the vis-server build
* fix(vis): replay legacy compactions per engine rules, tolerate bad cron payloads
- treat every record without keptUserMessageCount (or with an explicit
legacyTail flag) as a verbatim-tail compaction, matching the engine's
readContextCompactionShapeInput instead of gating on compactedCount
- derive tokensAfter from the reconstructed shape when the record omits
it, instead of keeping the stale pre-compaction fill
- skip malformed cron.delete / cron.cursor payloads instead of throwing
* feat(cli): add the kimi session list subcommand
- add the session command group with list: cwd scope by default, --all/--cwd/--archived/--limit/--json
- pass includeArchived through the SDK listSessions options (v2 klient query, v1 includeArchive mapping)
* docs: condense the session list changeset to one sentence
* fix(cli): sanitize session list rows and tidy option types
- strip control characters and line breaks from user-controlled row fields
- declare cwd/limit as plain optional properties without undefined unions
* fix(agent-core-v2): persist plan.revision as agent-relative key
- replace the session-scoped `path` field in durable plan.revision records
with an agent-relative `key`, resolved to a display path at read and
projection time against the current agent/session scope
- migrate legacy `path` records during wire restore and rewrite the journal
once migration succeeds, emitting low-cardinality
`wire_plan_revision_migrated` telemetry
- tolerate journal truncation during the migration rebuild and keep the
legacy `path` display in cold transcript folds for unmigrated records
- keep external transcript marker `path` and meta `reviewPath` projections
unchanged
* perf(agent-core-v2): fork sessions without materializing the target
- copy session files byte-for-byte (wire.jsonl included, parallel file
writes) and append the forked marker per agent instead of parsing and
rewriting every wire journal
- write the forked session's state.json, agent registry, and session
index entry directly without creating a live session or agent scopes;
fork returns SessionMeta and SessionForkedEvent drops the scope handle
- keep turnIndex truncation on the per-record path
- kap-server fork/createChild routes, the klient facade and wire
contract, and the node-sdk forkSession resume the forked session
through the normal resume path when a live handle is needed
- stop healing truncated source wires during fork; the forked session
repairs its own copy lazily on resume
- add the `kimi fork [--cwd] [-y]` CLI command
Tower mode is now entered only manually — /tower on, or /tower
<base-branch> to also pin the local branch missions merge back into. The
agent can no longer enter it on its own: TowerInit refuses while the mode
is off and points at the slash command.
/tower <base-branch> is deterministic end to end: a missing base branch is
created from the current checkout (uncommitted changes committed onto it
as a labeled WIP snapshot), the checkout switches to it, and the tower
workspace is initialized immediately instead of relying on the model to
apply the base. With an existing workspace the tower rebases onto the
requested base when no missions are open and refuses naming the blocking
missions otherwise. The base rides the tower_mode.enter event into the new
tower.base state key and TowerInit falls back to it.
Tower agent deaths (failed/timed_out/killed/lost) are recorded in the
tower protocol: TowerStatus marks dead roster entries and warns about
missions whose owner died, with a resume hint. The tower console prompt
now requires a per-worker deliverables summary before TowerTeardown.
The session profile REST surface accepts tower_base so web clients can
turn tower mode on with /tower <base-branch> instead of sending the
argument as a prompt.
Co-authored-by: konghuanjun <konghuanjun@moonshot.ai>
* feat(agent-core-v2): report enabled experimental flags in session_started telemetry
Add a sorted, comma-separated experimental_flags property to the v2
session_started event so feature-gated metrics gain a session-granular
exposure denominator, and carry the post-apply enabled set on the TUI
experimental_features_apply event to bound mid-session flag flips.
* feat(node-sdk): carry experimental flags on the harness session_started row
The v2 in-process path emits session_started twice (engine-side from
SessionLifecycleService, harness-side from KimiHarness), and only the
engine row carried experimental_flags, so consumers could double-count
or miss the flag dimension. Merge a per-emission dynamic getter into the
harness row, wired to the in-process engine's flag service, so both
rows report the same enabled flag set.
* fix(node-sdk): keep experimental_flags canonical on session_started
A caller-supplied experimental_flags in per-call sessionStartedProperties
could overwrite the engine-owned dynamic value, breaking row-to-row flag
consistency. Merge the dynamic properties after the session-scoped ones
so engine-owned keys always win.
* fix(agent-core-v2): count tower as exposure only once assembled
The tower flag reacts live to mid-process flips, but TowerFeature's
tools and profiles are assembled at App scope construction, so a session
started after an in-process flip cannot actually use tower. Filter it
out of experimental_flags on both session_started producers unless
isTowerFeatureAssembled says the feature is assembled in this process,
keeping the exposure denominator honest.
* test: recalibrate fixtures for the added constructor param and drop timing-sensitive tower assertion
The WorkspaceInstanceManager test builds the service with positional
args; the new flags param shifted unitHostFactory one slot. The tower
inclusion assertion in the SDK integration test depended on feature
assembly winning the race against async config load, which slow CI
runners lose; tower assembled-state coverage stays with the tower
service tests.
* refactor(agent-core-v2): move flag exposure gating into the flag definition
Telemetry consumers hardcoded tower's assemble-at-startup semantics to
keep it out of experimental_flags until assembled. Push the gate into
FlagDefinitionInput as an optional isExposed predicate owned by the
flag's own domain, expose it as IFlagService.exposedIds(), and let both
session_started producers call it — no feature-specific knowledge leaks
into the SDK or the session lifecycle.
* feat(cli): compress native update artifacts and decompress them while staging
Co-authored-by: qer <wbxl2000@outlook.com>
* fix(cli): generate compressed native artifacts in the publish job
The zip's checksum never pairs with the bare executable the updater
verifies after inflating, and artifacts produced in the matrix job never
leave the runner (the workflow's upload-artifact path lists only the
zip). Extract each zip in the publish job, hash the bare executable, and
emit the .zst/.tar.gz artifacts there so the manifest entry pairs
checksum with what compressed inflates to, and everything new reaches
the release via the existing upload glob — no workflow changes needed.
Co-authored-by: qer <wbxl2000@outlook.com>
* fix(cli): keep the .exe suffix in windows manifest filenames
The updater's bare-binary fallback downloads entry.filename, and the CDN
layout carries .exe on Windows — without it the fallback 404s. The .zst
and .tar.gz artifact names stay unchanged. Also fold the manifest
coverage into the pre-existing release-artifacts test (its fake-zip
fixture predates extraction) and pin the end-to-end chain there.
Co-authored-by: qer <wbxl2000@outlook.com>
---------
Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
Co-authored-by: qer <wbxl2000@outlook.com>
* refactor(agent-core-v2): migrate todo domain to agent-scoped DI service
* refactor(agent-core-v2): migrate skill domain to agent-scoped DI service
* refactor(agent-core-v2): migrate reminder domain to agent-scoped DI service
* refactor(agent-core-v2): migrate interaction domain to agent-scoped DI service
* refactor(agent-core-v2): migrate cron domain to agent-scoped DI service
* refactor(agent-core-v2): migrate dateChange domain to agent-scoped DI service
* refactor(agent-core-v2): migrate goal domain to agent-scoped DI service
* refactor(agent-core-v2): remove agent runtime infrastructure
* docs(agent-core-v2): rewrite agent domain standard as agent-scoped DI service
* fix(agent-core-v2): restore actor services on late feature re-provide and order agent-created events after metadata registration
TUI copy for the three permission modes (manual/yolo/auto) now uses the
new display names and descriptions across the /permission selector,
footer badge, toggle notices, goal/swarm start prompts, session replay,
and /status. The /yolo and /auto commands are renamed to
/ask-when-needed and /never-ask, with the old names kept as aliases.
* feat(agent-core-v2): require approval for dangerous bash commands in all permission modes
* feat(agent-core-v2): deny dangerous commands in auto mode, unwrap command launchers, and skip the guard for non-interactive hosts
* feat(agent-core-v2): support disabling the dangerous-command guard via config
* test(node-sdk): project v2's env-materialized empty permission section in config parity
* fix(cli): give the interactive update check a longer CDN timeout
`kimi update` shared the 3-second CDN fetch budget sized for passive
background checks. Every CLI invocation is a fresh process paying full
DNS+TCP+TLS setup, so a slow connection to the CDN intermittently
aborted the interactive check with a raw "This operation was aborted".
Thread a per-request timeout through the CDN fetch helpers and
refreshUpdateCache; the interactive upgrade command now passes a 10
second budget (INTERACTIVE_UPDATE_CHECK_TIMEOUT_MS) while all
background refresh paths keep the 3-second default.
* refactor(cli): drop motivational comments and simplify the update-check changeset
* docs(cli): reword the update-check changeset
* docs(cli): English changeset for the update-check timeout
---------
Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
* chore: sync web dist from code-app
code-app: 758f4587d10e28de8ac04678df8e379ca0f10387
* chore: consolidate web dist changesets by theme
* chore: trim web dist changesets to headline items
* chore: drop web prefix from fix-known-issues changeset
* chore: drop web-mobile-interaction changeset as duplicative of existing mobile entries
* fix(secondary-model): stop rewriting the section when providers refresh or are removed
Provider refresh, provider deletion/rename, catalog/registry import,
OAuth logout, and SDK removeProvider used to cascade into the user's
[secondary_model] block: pool entries were silently pruned, and the
whole section was deleted when its effective default dangled. The
cascade ran from a cache-refresh path (including an unattended 6h
scheduler), so upstream model-list changes could irreversibly destroy
hand-written configuration without any notice.
Config is user intent; the catalog is an availability snapshot. Stop
rewriting the section on every provider/models writer. An entry whose
model no longer resolves fails pool validation on the next session
create with a message naming the offending alias, which is the same
fail-fast contract hand-written typos already had.
* chore(sdk): add changeset for the removed secondary-model cascade export
* Delete .changeset/sdk-remove-secondary-model-cascade.md
Signed-off-by: 7Sageer <sag77r@hotmail.com>
* Delete .changeset/secondary-model-no-silent-rewrite.md
Signed-off-by: 7Sageer <sag77r@hotmail.com>
---------
Signed-off-by: 7Sageer <sag77r@hotmail.com>
Concurrent openSession/attachResumedSession calls for the same webview
both missed the sessions map before either wrapped the SDK session, so
one Session facade got two SessionRuntimes. The overwritten runtime
leaked and kept broadcasting, doubling every streamed delta and tool
call in the view. Queue opens, attaches, and detaches per webviewId so
the second caller sees the first one's runtime.
Add a liveness watchdog on the management and HTTP tunnel WebSockets
(client ping every 30s, terminate after 300s without inbound activity)
so the client recovers when a relay redeploy drops connections without
a close frame. Treat registration failures after a successful session
as transient and keep backing off instead of stopping permanently.
v2 engine status events carry contextTokens/maxContextTokens but never
contextUsage, so appState.contextUsage was only refreshed by getStatus
pulls and then went stale while the token counts kept updating live.
The /usage panel and footer render the ratio as a bar but recompute the
percentage text from the counts, so a stale ratio showed as a bar that
disagreed with the percentage (e.g. bar ~74% next to "18% (180k / 1M)"
after compaction or a model switch).
Recompute the ratio from the post-patch token counts whenever a status
update touches contextTokens or maxContextTokens without carrying an
explicit contextUsage. v1 events carry the ratio and are unaffected.
Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
* fix(kimi-code): render newlines instead of literal backslash-n in rc output
* fix(kimi-code): print plain URL in rc output when hyperlinks are unsupported
* feat(kimi-code): add remote control web tunnel
Add CLI and TUI entry points for exposing the local web UI remotely.
Bridge HTTP and WebSocket traffic with local authentication and reconnect handling.
* fix(kimi-code): prevent remote control websocket crash
* fix(kimi-code): align websocket dependency versions
* fix(kimi-code): harden remote control connection setup
Reconnect when management closes during the HTTP tunnel handshake.
Reject non-loopback Remote Control binds whose CSP blocks path bootstrap.
* fix(kimi-code): fix remote control rewriting, caching, and WS frame loss
* feat(kimi-code): add remote control QR output
* build: update pnpm dependencies hash
* refactor(kimi-code): remove the --allow-remote-terminals flag
* feat(kimi-code): add remote control lock, rc command, and QR fixes
* fix(kap-server): broadcast user prompts to all session clients on submit
- agent-core-v2: emit prompt.submitted (status running|queued) at enqueue and prompt.started when the turn launches
- kap-server: project prompt.submitted/prompt.started into transcript prompt entities and the live transcript REST response
- update flake.nix pnpmDeps hash for the PR lockfile
* fix(node-sdk): drop v2-only prompt.started from SDK event stream
- event-mapper: add prompt.started to the dropped v2-only prompt lifecycle types (parity with submitted/completed/aborted/steered)
- cli test: assert only visible sub-commands and stub the experimental flag env for determinism
* ci(pkg-pr-new): post custom install comment for npm 12 compatibility
* feat(kimi-code): render remote control QR as inline image on capable terminals
* feat(kimi-code): improve remote control terminal output
- add onboarding, security, device management, and help guidance
- show compact clickable links and QR image fallback details
- report relay and remote device connection lifecycle
* test(agent-core-v2): update tool event snapshot
* revert(ci): keep preview workflow unchanged in rc pr
---------
Co-authored-by: liruifengv <liruifeng1024@gmail.com>
* fix(tui): render /plugins marketplace before version lookups resolve
The Third-party/Official tabs waited on the slowest GitHub
releases/latest lookup before painting any catalog row, with no
timeout (undici defaults: 10s connect, 300s headers) and no caching,
so a stalled connection to github.com left the panel on "Loading
marketplace…" for minutes on every /plugins open.
Load in two phases: render the catalog as soon as it is parsed, then
resolve latest versions in the background (5s per-lookup timeout,
per-entry failures degrade to a missing badge) and refresh when they
land. Update badges appear slightly later; row order is unaffected
since sorting only depends on installed state.
* refactor(tui): move marketplace version lookup timeout to constants
Per AGENTS.md, application constants live in src/constant/ — moves
MARKETPLACE_VERSION_LOOKUP_TIMEOUT_MS next to the other marketplace
constants in constant/app.ts.
* fix(tui): resolve marketplace versions before built-in injection
Phase 1 injected built-in capability rows into the marketplace before
phase 2 ran, masking the matching catalog entries' GitHub sources
behind capability:<id> rows — so installed built-ins could never
receive update badges (the pre-change resolve-then-inject ordering
preserved them).
Keep the raw parsed catalog for phase 2, re-apply withBuiltInEntries
after versions resolve (resolved versions flow onto capability rows),
and keep the built-ins-only fallback when the catalog is unreachable.
* fix(tui): surface marketplace parse errors instead of masking them
The phase-1 catch converted every failure into a built-ins-only loaded
marketplace, hiding malformed-catalog errors behind a silently empty
Curated tab. Restore the error state for all phase-1 failures — the
panel already keeps built-in capability rows installable in the
Official tab while the error is displayed.
---------
Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
* fix(kimi-code): persist picked thinking effort up to the model's default effort
The persistence gate kept the model's top declared effort session-only
unconditionally, so users whose delivered default_effort is the top tier
(e.g. max) could never save an explicit pick of it. Compare the pick
against the model's default_effort instead, using support_efforts as the
strength ordering: picks above the default stay session-only, picks at
or below it persist. Models without a declared default keep the
historical top-tier rule. The same change lands in the VS Code
extension's mirrored logic.
* docs(kimi-code): document the effective-default ceiling for effort persistence
Clarify in both apps' comments, the changeset, and the config docs that
the persistence ceiling is the model's effective default effort, whether
declared via the catalog / overrides or synthesized by the protocol
profile inference (Claude models resolve to high, so an xhigh pick is
session-only there). Pin the inference path with tests in both apps.
* fix(vscode): resolve the save-config model with its provider type
Mirror the TUI's effectiveModelForHost: without the provider type the
Anthropic fallback profile (e.g. claude-latest) never matches, so the
inferred default effort that gates persistence was missed and an
above-default pick could persist where the TUI keeps it session-only.
* Delete .changeset/persist-effort-up-to-model-default.md
Signed-off-by: 7Sageer <sag77r@hotmail.com>
* fix(vscode): seed the persisted effort with the effective-default ceiling
* fix(vscode): project webview models with the provider type
* fix(kimi-code): apply a session-only effort pick to the runtime in the /provider flow
* fix(vscode): update the persisted-effort seed on model-switch saves
* docs(kimi-code): drop the default_effort persistence-ceiling note
---------
Signed-off-by: 7Sageer <sag77r@hotmail.com>
* fix(tower): remove command queue
* feat(agent-core-v2): support an explicit base branch in TowerInit
* fix(kimi-code): keep tower objective order across a mid-turn compaction
* feat(agent-core-v2): add abandoned tower mission status to release stale scopes
* chore: consolidate tower changesets into one feature entry
* chore: consolidate tower changesets into one feature entry
---------
Co-authored-by: konghuanjun <konghuanjun@moonshot.ai>
* feat(agent-core-v2): turn /tower into a mode parallel to plan mode
* feat(agent-core-v2): align /tower command semantics with the original skill behavior
* fix(tui): harden the /tower command against mid-turn objectives, legacy engines, and stale status
* fix(agent-core-v2): keep restored tower state inert while the feature flag is off
* fix(agent-core-v2): include TowerInit in the mode tool overlay and report flag-gated tower state
* feat(agent-core-v2): expose tower control tools statically and make the mode injection history-derived
* fix(tui): warn that tower mode needs a restart after a live flag flip; drop redundant undefined from SessionStatus mode fields
* fix(agent-core-v2): let tower mode exit clear persisted state while the flag is off
* fix(agent-core-v2): emit the tower exit reminder through a disabled flag and drop the redundant REST state comparison
* fix(tui): show the Tower mode status row only when the experiment is available
* fix(agent-core-v2): confine tower mode to the main agent and always re-assert it for objectives
* feat(kap-server): project tower mode into transcript modes and reassert explicit toggles
* fix(agent-core-v2): fold the main-agent invariant into the effective tower state
* fix(kap-server): gate the cold tower mode badge behind the experiment flag
* fix(agent-core-v2): reapply the tower tool overlay after a profile bind; fix(kap-server): clear cold tower badges on non-main agents
* fix(protocol): mirror towerMode and tower_mode in the shared zod schemas
* test(agent-core-v2): adapt tower tests to the agent lifecycle context architecture
* chore(agent-core-v2): regenerate the wire manifest; test(node-sdk): look up the main agent via findAgentHandle
* fix(agent-core-v2): exit a replayed tower mode when the workspace belongs to another session
* fix(agent-core-v2): carry tower ownership in the enter record so forks clear inherited mode
* fix(agent-core-v2): apply the tower overlay before dispatching enter and repair it on status updates
* fix(agent-core-v2): validate store ownership before entering tower mode
* fix(agent-core-v2): claim the repository tower owner at enter; fix(tui): confirm mode activation before reporting success
* fix(agent-core-v2): make the first tower claim exclusive and refuse adoption over a live owner
* feat(agent-core-v2): guard tower adoption and teardown with a cross-process ownership lease
* revert(agent-core-v2): drop the cross-process lease and enter-time claim, keep ownership checks process-local
* fix(agent-core): hide the v2-only tower flag from the legacy experiments list
* fix(agent-core-v2): keep tower mode inert until the tower feature is assembled
A live /experiments flip refreshes the flag but cannot re-run App-scope
feature assembly, so the tower tools/profile stay unregistered until a
restart. Gate enter()/isActive on the assembly fact and say so in the
TUI error. Also resolve the AGENTS.md conflict block committed by the
merge, and widen the TUI experimentalFlag type to string now that flags
live in two registries.
* fix(kap-server): gate the cold tower badge on tower feature assembly
Same live-flip gap as the mode machinery: a persisted tower_mode.enter
plus a flag enabled without a restart would still show the badge while
the feature is inert. Require isTowerFeatureAssembled() alongside the
flag, re-exported from agent-core-v2.
* fix(agent-core-v2): liveness-aware tower entry and per-App assembly state
enter() now mirrors TowerInit's adoption rule: a stored owner blocks
entry only while that session is live in this process, so a new session
can enter the mode and reach TowerInit to adopt a stale tower. The
assembly marker is keyed by each App's flag service (WeakSet) instead of
process-global module state, so coexisting Apps no longer leak assembly
into one another.
* fix(agent-core-v2): keep stale-owner adoption across resume; reject tower updates that do not take
exitForeignTower now treats a stored owner as foreign only while that
session is live, so a mode entered by adopting a dead owner's tower
survives close/restart. The TUI validates the model prerequisite before
enabling tower for an objective, and the REST agent_config path throws
session.tower_mode_invalid when enter() did not take effect instead of
acknowledging a no-op.
* fix(agent-core-v2): clear the tower assembly marker when the feature unloads
Register the WeakSet cleanup via the feature's onDispose so the
capability follows the managed unit's lifecycle — after
unprovideUnit('tower'), isActive/enter() no longer treat the retracted
tool set as assembled.
* fix(agent-core-v2): publish tower deactivation on gate loss; reject refused setTowerMode in the SDK
isActive now reconciles its projection: restore and feature-manager unit
changes publish AgentStatusUpdated({ towerMode: false }) when the
persisted mode lost a gate (flag off at runtime, feature unloaded), so
live transcript badges and TUI state stop showing an inert mode. The
SDK's setTowerMode(true) verifies the effective state and throws
session.tower_mode_invalid, matching the REST path.
* fix(agent-core-v2): reconcile tower projection on config changes and cold ownership moves
The last unreconciled gate inputs: a live setConfig writing the
experimental section (no session reload, no units event) now republishes
towerMode:false through the config-change subscription, and the cold
transcript badge mirrors the same ownership/liveness rule as enter() —
retained while the store owner is this session or no live session, cleared
once a live session elsewhere owns the tower.
* fix(agent-core-v2): reconcile the tower projection in both directions
The OFF-only reconcile left a hole: re-enabling the flag in the same
process made isActive true again with no towerMode:true publish, and
enter() could not heal it (it early-returns when already effective).
The projection now tracks the last published state and emits both
false→true and true→false transitions from the same restore/units/config
triggers; direct publishes (enter/exit/restoreTowerTools) keep the
tracker in sync.
* fix(agent-core-v2): validate forked tower ownership even while the flag is off
exitForeignTower's flag short-circuit let a fork restored while the
experiment was disabled keep its inherited enter record; re-enabling the
flag later revived both source and fork over the same store. Ownership
validation is flag-independent state hygiene, so restore now runs it
regardless of the effective flag — a live foreign owner clears the
fork's persisted mode before any gate can rise again.
* fix(agent-core-v2): veto tower tools while the tower experiment is off
With the feature assembled and the tool overlay active, disabling the
flag live left TowerInit/TowerTeardown callable — they have no flag
check — so prompts could still mutate or dismantle .tower/ while the
experiment reported disabled. A dedicated onBeforeExecuteTool hook now
denies every tower tool whenever the flag is off, mirroring the TodoList
veto.
* fix(agent-core-v2): keep tower worker write isolation when the flag turns off
The worker Write/Edit guard is identity-scoped (tower-worker profile),
not feature-activity-scoped: disabling the experiment live must not let
already-spawned detached workers write into the main checkout or other
worktrees. The guard no longer checks the flag; the tower-tool veto
added earlier covers protocol access instead.
* test(agent-core-v2): make tower tests hermetic for CI
Three CI-only failures: towerService git fixtures committed without a
repo-local identity (CI has no global gitconfig), the node-sdk tower
positive tests relied on the developer shell's
KIMI_CODE_EXPERIMENTAL_FLAG=1 master switch instead of enabling the
tower flag explicitly, and the legacy harness experimental-features
expectation still listed the tower entry removed from the v1 registry.