Commit graph

1684 commits

Author SHA1 Message Date
HydrogenE7
874d9abb32
feat: add /provider refresh subcommand (#4316)
Some checks are pending
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
CI / release-workflow-tests (push) Waiting to run
2026-10-21 20:40:00 +08:00
7Sageer
0a90e2e8a2
fix(agent-core-v2): reclaim session locks from zombie processes (#4320) 2026-10-21 20:39:00 +08:00
7Sageer
366fafbf92
feat(kap-server): reclaim idle sessions (#4284)
* feat(kap-server): reclaim idle sessions

* test: trim idle session reclaim test duplication

* test: fix idle reaper fake typing

* fix(kap-server): preserve session state during idle reclaim

* fix(kap-server): resume cold sessions for tool routes

* fix(kap-server): report failed WS session resumes

* refactor(agent-core-v2): let features declare session idle retention

Move the cron, goal, and lifecycle-hook reclaim guards out of SessionManager
into a SessionRetentionContribution collection that each feature contributes,
check retention once under the session lease, and drop the dead optional
task-service branches in the tasks route.

* refactor(agent-core-v2): measure session idle from the activity view

* refactor(agent-core-v2): reclaim idle sessions silently instead of retaining hooked sessions

* fix(kap-server): only resume explicitly requested sessions in tool routes

* refactor(agent-core-v2): inline the cron idle-reclaim guard and stop retaining active goals

* fix(kap-server): reject invalid idle reclaim timeouts

* fix(kap-server): preserve rating evaluation across idle reclaim

* test(kap-server): trim idle reclaim tests

* fix(kap-server): validate idle reclaim config early

* refactor(agent-core-v2): rename the reclaim resume source and derive lifecycle literal unions

* refactor(agent-core-v2): keep the reclaim lifecycle tags off the public lifecycle interface

* fix(agent-core-v2): drop the reclaim marker once a session is archived

* Implement session unload after 30 minutes of idle time

Updated session management to unload sessions after 30 minutes of inactivity for both web and desktop applications.

Signed-off-by: 7Sageer <sag77r@hotmail.com>

* fix(agent-core-v2): reclaim sessions with exited terminals

---------

Signed-off-by: 7Sageer <sag77r@hotmail.com>
2026-10-21 19:27:25 +08:00
HydrogenE7
256ce61f0c
perf(agent-core-v2): speed up large session resume (#4313) 2026-10-21 17:20:19 +08:00
Kimi Agent
4bad441fef
chore: sync release/2026-10-21 (2.3.0) back to main (#4306)
* ci: release packages (#4288)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* revert: remove default workspace session creation (#4295)

(cherry picked from commit 83c7909be9)

* chore: merge release/2026-10-20 into release/2026-10-21 (#4294)

Bring the cloud-gated model switch confirmation (#4286, #4292) and the
queued /compact (#4276, #4279) onto main via the release back-sync.

The two changesets that rode along with the original squash
(.changeset/model-switch-confirm-dialog.md,
.changeset/queue-compact-command.md) are excluded here: they were
consumed by the 2.3.0 release and must not be re-consumed on main.

(cherry picked from commit 3f80896a79)

* chore: sync web dist from code-app (#4304)

code-app: 913137036c35c608f3a487eb2c7b4a8815b53b95

The stray .changeset/web-interaction-polish.md carried by the dist
payload is excluded: it was consumed by the 2.3.0 release and never
existed on main.

(cherry picked from commit d36071ede6)

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: qer <wbxl2000@outlook.com>
Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
2026-10-21 14:50:45 +08:00
Kimi Agent
95eeeecf9b
docs(changelog): sync 2.3.0 from apps/kimi-code/CHANGELOG.md (#4305)
* docs(changelog): sync 2.3.0 from apps/kimi-code/CHANGELOG.md

* docs(changelog): drop VS Code 0.8.3 entry from 2.3.0 CLI changelog

---------

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
2026-10-21 13:52:30 +08:00
Haozhe
67325c1b25
fix(transcript): realign rebuilt turn ordinals to wire ids and mark wedged turns (#4280)
Some checks are pending
CI / release-workflow-tests (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
* fix(transcript): realign rebuilt turn ordinals to wire ids and mark wedged turns

Cold transcript rebuilds numbered materialized turns 0..N while the live
projector assigns ordinal=wireId, so a session rebuilt after a restart got a
shifted axis that no longer aligned with what clients had cached live, and a
turn whose loop died before writing a terminal event was rebuilt as a fake
completed turn with no timestamps.

foldWireRecordFacts now reassigns every matched rebuilt turn to its wire turn
id (leaving holes for folded turns), restores startedAt from the
agent.turn.started / turn.prompt records, and marks a turn with no terminal
event as wedged (state failed + wedged flag) once a later turn prompt exists
in the wire; the tail turn is only wedged when it is not the live active one.
The live projector closes the previous running turn as wedged when a new turn
starts. The wedged marker is an additive optional field so released clients
keep parsing transcripts and render the turn as failed.

* feat(agent-core-v2): surface silent notification-delivery and persistence failures

The wedged-turn incident showed a main agent loop can stall for hours with
zero diagnostics: task notifications pooled in memory, a latched or hung wire
flush swallowed every subsequent record, and the running turn produced no
watchdog output.

- AppendLogStore warns once when an append is accepted while a storage
  failure is latched, and warns when a flush stays pending past 30s
  (repeating every 10min) with scope/key/pending counts.
- WireService routes append failures to ILogService in addition to
  onUnexpectedError so they land in the daemon log.
- AgentLoopService arms a per-turn watchdog that warns after 10min without
  observable progress (steps, streaming partials, machine phase), including
  pending notification/pause/queue state; loop.notify and nudge consumption
  log buffered/drained counts at debug level.
- AgentTaskService warns when lifecycle guards silently drop task
  notifications or terminal events, and debug-logs in-process redelivery
  suppression.
- EventDispatcherService warns once per episode when dispatch is stuck for
  over 30s and events keep queueing behind it.

* test(agent-core-v2): quiesce the spawned notification turn before counting leaked timers

With the loop turn watchdog armed, a notification-driven turn that happens
to be running at the assertion holds a legitimate interval, making the
global timer count scheduling-dependent. Cancel any spawned turn and pump
the clock until the loop is idle before counting.

* chore: add changeset for the wedged-turn transcript fix
2026-10-20 18:00:19 +08:00
7Sageer
3079e9515f
feat(agent-core-v2): add cross-process session occupancy lock (#4246)
* feat(agent-core-v2): add cross-process session occupancy lock

Multiple clients (TUI / kap-server / VS Code / ACP) running core in
separate processes could open the same session and corrupt each
other's wire.jsonl and metadata. Each session now holds a cross-process
occupancy lock ({homeDir}/locks/sessions/{id}.lock) taken only while
writing: runs acquire it on submit / compact / undo / cron / delete /
fork / cold-archive, the append log holds it before flushing, and a
stale check compares the main agent wire's on-disk length with the
length this process knows.

Collisions surface as session.occupied (holder in details); writes by
another client detected after acquire surface as session.stale and the
caller reloads before continuing. kap-server maps them to
SESSION_OCCUPIED (40903) / SESSION_STALE (40930), reloads the session
on stale, and re-attaches WS subscriptions; the TUI shows an occupancy
dialog (retry/cancel) or reloads and replays history keeping the input;
print exits with code 4 on occupied and reloads automatically on stale;
VS Code / ACP get minimal occupancy notices. Locks are released a few
seconds after the session goes idle, on close, and on process exit;
locking I/O failures degrade to unlocked operation with a warning.

* docs: document session occupancy error codes and lock directory

* fix: address codex review on session occupancy lock

- metadata: re-read state.json on the first write of each lock-hold
  epoch (holdToken), so pure-metadata changes made by another client
  (title, archive) are not clobbered by turn-end lastPrompt writes
- lifecycle: hold an explicit lease across live archive(), matching
  delete(), so the idle release timer cannot drop the lock mid-teardown
- tui: route the occupied dialog's Cancel selection through the same
  cleanup as Esc (restore input, release recalled media)
- acp: tell stale-session users to close and reopen the session
- append-log: warn when retirement drops records kept in memory because
  the session lock was unavailable

* fix: always run the staleness check in beginSessionRun

The prompt channels (AgentPromptChannel.submit/submitSteer, kap
/prompts, promptWithSkills) write prompt metadata before calling
loop.submit, and the metadata write acquires the session lock first.
beginSessionRun then short-circuited on 'already held' and skipped the
wire-length staleness check, so the main prompt path never detected
updates written by another client. Drop the already-held shortcut: the
check is a single stat and always passes while the lock is continuously
held, so every acquisition path now runs it regardless of order.

* fix(print): preserve occupied handling on the stale retry

If another client acquires the session between the reload and the
retry, the retried turn now goes through the same conflict handler:
session.occupied reports to stderr / stream-json and exits with code 4
instead of bubbling out as exit code 1.

* fix: do not mistake own in-flight writes for external modification

storage.append grows the file (writeFile) before fsync/close complete,
and knownLength only catches up afterwards; a beginSessionRun landing
in that window (steer, queued prompts, cron fires during a turn) was
misjudged as session.stale and deleted the lock file mid-turn. Track
in-flight bytes per log and compare disk against known + in-flight.
Cover the analogous rewrite window (post-rename syncDir) with an
expected-final-length marker.

* fix: bound the staleness comparison and check once per lock hold

The equality check disk !== known + inFlight moved the false-positive
window to before the append lands (mkdir/open) and into chunked
writes, so beginSessionRun during a turn (steer, cron, queued prompts)
could misjudge, delete the lock file mid-turn, and later append behind
another client. Compare known <= disk <= known + inFlight instead, and
evaluate the check only on a fresh hold (holdToken epoch): re-entrant
runs pass through without a stat, matching the RFC's 'already held
passes through' while every acquisition path still triggers the check
exactly once per hold.

Also unify the occupancy prompt copy across clients: the engine error
message is now the single user-facing text ('该会话正在被其他 Kimi
Code 进程使用;请停止其他进程中的会话或退出该进程后重试'), and the
TUI dialog, /compact /undo errors, print output, and the VS Code
fallback all display it instead of maintaining their own wordings.

* fix: address third-round codex review

- metadata: hold an explicit lease across each state.json write so the
  idle release timer cannot unlink the lock mid-write
- print: preflight the session lock before goal creation; make goal
  creation idempotent and emit the goal summary only for attempts that
  did not fail with session.stale, so a stale reload + retry neither
  duplicates the goal nor the summary
- tui: route every prompt-launch path (plain, goal steer, plugin
  command, inline skill, batch steer) through one conflict handler
  with the occupied dialog and stale reload + input restore
- tui: snapshot and restore the attachment store across stale reloads
  so pasted media placeholders still resolve after history replay

* fix: move session occupancy to a fresh error code, use English copy, release locks on exit

SESSION_OCCUPIED reused 40903, which belonged to PROMPT_ALREADY_COMPLETED until #3747 retired it, and web clients still allowlist 40903 for that old meaning; reusing it conflated the two semantics. Move session occupancy to the never-used 40931 and update the server API reference in both locales.

The occupied error message was hardcoded in Chinese while every other engine error is English, so the TUI, print mode, VS Code, and ACP clients all rendered mixed-language output; replace it with an English equivalent.

The lock release hook ran on 'beforeExit', which never fires when the process leaves through process.exit (SIGHUP in the TUI goes through emergencyTerminalExit), leaving stale lock files that could keep a session looking occupied forever after a hostname change or pid reuse. releaseAll is fully synchronous, so hook 'exit' instead.

* fix(agent-core-v2): decide prompt-derived titles after re-reading session metadata

applyPromptMetadataUpdate decided whether to derive a title from the
prompt from the in-memory metadata cache, which is only refreshed when
the session lock is re-acquired. If another client named the session in
the meantime, the stale cache still looked untitled, so the next prompt
from this client overwrote the other client's title — both on the stale
path, where the prompt is rejected afterwards, and on the fresh path,
where the other client only changed the title on disk.

Move the untitled check into SessionMetadata.applyPromptMetadata, which
runs after ensureWriteOwnership() has re-read state.json, so the
decision is based on the latest persisted metadata. The published
SessionMetaUpdated event now carries the derived title only when it was
actually written.

* fix: address fourth-round codex review

- vscode: classify session.occupied and session.stale as preflight errors so the webview toasts them instead of silently swallowing the send, and give session.occupied the same English copy the engine emits (the toast text comes from getUserMessage in the extension host).
- engine: beginSessionRun now takes the session context and agent lifecycle service, and on the first check of each lock hold it runs externallyModified over every loaded agent's wire (scope agents/<agentId>, key wire.jsonl) instead of only the main agent's, so a fork that only touched a subagent journal is detected as stale. All four call sites (loop submit, manual compaction begin, undo, print preflight) pass the extra dependency.
- tui: keep the request in flight across a stale reload instead of dropping to idle, so input submitted during the reload queues rather than racing the closing session; park the queue around switchToSession (resetSessionRuntime would clear it) and drain it into the reloaded session afterwards; when restoring the rejected text, prepend it before content the user typed during the reload instead of overwriting it.
- kap-server: clear the in-flight turn tracker and subagent roster in detachSession so a reattached session no longer reports stale in-flight turns or running subagents in REST snapshots and WS resyncs.

* fix: harden session conflict recovery

Detect external appends that race journal reads so a later run cannot miss session.stale. Keep deferred wire migrations pending and finish them before appending, while rejecting the append if migration still cannot complete. Restore the complete plugin command after an occupied cancellation, including commands without arguments.

* fix: scope session staleness cache to session context

Replace the process-global session-id map with a WeakMap keyed by ISessionContext so closed and reloaded sessions do not retain cache entries for the lifetime of the process.

* fix: document session conflicts for metadata routes

Declare SESSION_OCCUPIED and SESSION_STALE in the response schemas for profile updates, title generation, and child creation. Cover the OpenAPI declarations and the existing HTTP 200 conflict envelopes with regression tests.

* refactor: centralize session conflict handling

Move session error mapping and stale reloads into one shared route helper, reuse shared conflict response declarations, and cover skill activation conflicts. Remove the duplicate prompt, session, and skill error mappers while preserving their existing envelopes.

* fix(sdk): restate session conflict errors

* fix(tui): keep the reloaded session open and resend after a stale conflict

* fix(agent-core-v2): lazily rebuild registered agents after a session reload

* refactor: simplify session conflict handling

* refactor: hygiene fixes from session-lock review

- kap-server: move SESSION_STALE to 40932 (collided with
  DEFAULT_WORKSPACE_UNAVAILABLE at 40930) and pin ErrorCode value
  uniqueness with a test
- node-sdk: fold six catch-and-restate copies into a restate() helper
- acp-server: sync mapPromptLaunchError docstring with the
  occupied/stale branches
- replace hardcoded session.stale/session.occupied literals with
  ErrorCodes constants
- inline the single-use sessionStaleError
- restore the strict timer-leak assertion with a warmup baseline
  instead of a blanket +1 allowance
- narrow SessionState.detached to ?: true

* refactor: introduce session-level run gate

- replace the beginSessionRun free function with ISessionRunGate, a
  Session-scoped service; loop/compaction/undo now inject one
  dependency instead of four, and sessionLock.ts no longer imports
  session-layer modules
- tryHold() absorbs the duplicated try/catch hold copies in
  wireService and sessionMetadataService
- resolve IAgentLifecycleService lazily inside the gate to avoid a
  construction-time cycle with agentLifecycleService

* refactor: tighten session lock and conflict recovery structure

- Narrow ISessionLockService to hold/tryHold/release/lease/held and share
  the hold bookkeeping between the memory and node-fs backends; drop
  holdToken and the module-level exit hook state.
- Session metadata refreshes on a new hold via onDidHold and skips agent
  registration through tryHold instead of catching session.occupied.
- AppendLogStore reads sizes through IFileSystemStorageService.sizeSync and
  exposes a generic write guard instead of a session-lock binding.
- kap: reload stale sessions only at the call sites that can raise
  session.stale and log reload failures; error mapping stays side-effect free.
- TUI: recover from a stale conflict through the in-place session reload with
  history replay, removing the same-session switch special case, the media
  store snapshot, and the queue parking.
- print: bound stale reloads with a simple retry loop.

* refactor(agent-core-v2): merge session lock release into run gate

* test(agent-core-v2): reuse append log fixtures

* refactor(agent-core-v2): break run gate and agent lifecycle dependency cycle

* refactor: reload stale sessions in core instead of each host

Stale detection already lived in core, but every host re-implemented the
recovery: TUI, print, and kap each closed and resumed the session, and TUI
and web resent the rejected input themselves.

Core now exposes reloadOnStale: on session.stale it closes and resumes the
session, lets the caller refresh, then retries the call once (undo reloads
and still rejects, since its count depends on what the user saw).

- kap: prompt submit, skill activation, and compact retry in place instead
  of returning 40932; undo still returns 40932 after reloading
- print: retries through reloadOnStale on the same session id and keeps the
  original permission mode to restore
- SDK: run-starting calls reload and retry internally; Session gains
  setStaleReloadHandler so hosts refresh before the retry
- TUI: drops its own reload/resend/queue-merge path; the stale handler
  replays history and keeps in-flight messages

* docs(server-api): note that only undo returns 40932 after a stale reload

* refactor(agent-core-v2): ask each agent's wire whether it was modified externally

* refactor(agent-core-v2): clarify agent restoration helper name

* Delete .changeset/ensure-agent-lazy-rebuild.md

Signed-off-by: 7Sageer <sag77r@hotmail.com>

* fix(tui): wrap session occupied notice

---------

Signed-off-by: 7Sageer <sag77r@hotmail.com>
2026-10-20 17:21:18 +08:00
Kimi Agent
5fec8d19a5
test(remote-control): split the tunnel end-to-end case and make transfer limits injectable (#4290)
Co-authored-by: kimi-agent-bot <317908118+kimi-agent-bot@users.noreply.github.com>
2026-10-20 16:52:03 +08:00
grapedge
ce0834a8f3
feat: share session rating rules across CLI and server (#4272) 2026-10-20 14:20:55 +08:00
Haozhe
5710c5496a
fix(kap-server): evict session event state on session close and archive (#4281)
Some checks are pending
CI / release-workflow-tests (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
2026-10-19 20:24:57 +08:00
qer
e5e56bc5fe
feat(server): place the default workspace under the home folder (#4277)
Some checks are pending
CI / release-workflow-tests (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
The default workspace lived in <Documents>/KimiCode/Default. On macOS the
first chat there triggered a Documents privacy prompt, and a denial blocked
every later chat until the user found the setting. Documents is also synced
by iCloud and OneDrive, and covered by Windows Controlled Folder Access.

Use ~/KimiCode/Default on every platform instead. This drops the Windows
PowerShell lookup, the XDG user-dirs parsing, and the documents_unavailable
reason; the error path is now always present.
2026-10-19 16:13:43 +08:00
qer
47002256a0
feat: add a default workspace for chats without a project (#4224)
* feat(server): create sessions in a default workspace when none is chosen

POST /api/v1/sessions accepts default_workspace: true, exclusive with
workspace_id and metadata.cwd. The server resolves <Documents>/KimiCode/Default
on every request, creates it on first use, and reuses it afterwards. A path
blocked by a file fails with 40409 and a permission error with 40411; the
server never relocates silently.

Workspace payloads on REST and WebSocket events carry is_default.

* fix(server): fail instead of relocating when Windows Documents cannot be resolved

A failed registry lookup used to fall back to %USERPROFILE%\Documents, which
could silently create a second default workspace when Documents is redirected
(for example by OneDrive). The lookup now fails with 40409, the failure is not
cached so the next request retries, and is_default reports false meanwhile.

* fix(server): resolve Windows Documents through the shell folder API

Reading User Shell Folders with reg.exe misses the default when the value is
absent, cannot expand every variable, and is blocked where registry tools are
disabled by policy. Ask Windows for the Documents folder through PowerShell
instead, forcing UTF-8 output so non-ASCII paths survive. A reported folder
that does not exist is treated as unresolved, so garbled output can never
create a workspace in the wrong place.

* test(server): assert the existing error code for a missing Windows Documents folder

* fix(server): start Windows PowerShell by absolute path

The Documents lookup spawned the bare name powershell.exe, so Windows
resolved it through the current directory and PATH. In an untrusted
checkout that lets a repository-provided powershell.exe run before the
trust gate. Resolve it under SystemRoot (falling back to windir and
then C:\Windows) instead.

* feat(server): report an unusable default workspace with its path and reason

Creating a session in the default workspace used to surface folder problems
as generic codes: 40409 when a file blocked the path or the Windows
Documents folder could not be located, 40411 on permission errors, and a
plain internal error for anything else. Clients could not tell the default
workspace apart from an ordinary missing directory, nor explain what to fix.

DefaultWorkspaceService now throws DefaultWorkspaceUnavailableError
(default_workspace.unavailable) carrying the folder path and one of
blocked_by_file, permission_denied, missing_parent, no_space, read_only,
invalid_path, documents_unavailable or unknown. ensure() also verifies that
a file can be created and removed in the folder, so a read-only folder is
reported before a session is placed there. The server maps the error to
40930 with { path, reason } in data.

* feat(server): make the default workspace location configurable

The default workspace was fixed at <Documents>/KimiCode/Default. Users who
keep chats on another disk, or whose Documents folder is synced, had no way
to move it.

Add a default_workspace.path setting in config.toml. It accepts an absolute
path or ~/..., and on Windows only a drive path or a full UNC share; the
value is checked for writability before it is saved and is never moved
silently. An invalid value in the file is reported as invalid_path instead
of falling back to the system location.

The server exposes GET and PATCH /api/v1/default-workspace with the
effective path, the saved custom path, the system path and the folder's
health. The section is kept out of GET /api/v1/config and rejected by
POST /api/v1/config so it has a single writer. Whenever the location
changes, through PATCH or an edit to config.toml, every registered
workspace broadcasts event.workspace.updated with its current is_default.

* feat(cli): add --default-workspace and expose the default workspace in the SDK

Add kimi --default-workspace to work in the shared default workspace instead
of the current directory. Both the interactive shell and print mode resolve
the folder through the engine before the session starts and change into it,
keeping PWD in sync; when the folder cannot be used, startup fails with its
path and reason. Resume hints become kimi --default-workspace -r <id> for
such sessions.

The session picker labels sessions in the default workspace as "Default
workspace" and copies a resume command without a cd for them. kimi doctor
reports the location and whether it can be used. The stty lookup excludes
both the launch directory and the new working directory, so a binary
planted in either is never executed.

The SDK gains KimiHarness.ensureDefaultWorkspace(), getDefaultWorkspacePath()
and getDefaultWorkspaceStatus(), maps default_workspace.unavailable to a
KimiError, and exports workspaceRootKey and DEFAULT_WORKSPACE_PROBLEM_MESSAGES.

* fix(server): never remove a write probe the check did not create

createExclusive resolves to false when the probe name already exists. The
write check ignored that result and went on to remove the path, which is a
recursive delete of an entry it did not create. Report the folder as
unknown instead and leave the entry alone.

* fix(server): declare 40001 on PATCH /default-workspace and log failed broadcasts

The PATCH route returns 40001 when the body fails validation, but its
OpenAPI response union only listed success and 40930, so generated clients
could not model it.

When the default workspace location changed but the workspace catalog
could not be read, the publisher dropped the broadcast without a trace.
Log a warning so the missing event.workspace.updated can be diagnosed.

* fix(cli): point the resume hint at the session folder after the default moves

A session started with --default-workspace printed
kimi --default-workspace -r <id> on exit even if default_workspace.path
changed while it was open. Following that hint moved into the new default
folder and refused the session, which still lives in the old one.

Repeat the flag only while the session folder is still the default
workspace; otherwise print cd <folder> && kimi -r <id>.

* refactor: trim the default workspace to what clients use

Keep session creation in the default workspace, the configurable
location, the 40930 error with its reason, and `kimi --default-workspace`.

Remove what no client needs:
- write probes, ancestor walks, and dangling-link checks; saving a
  location now creates the folder, and use-time errors come from mkdir
- `system_path` and `problem` in the status response
- the workspace-update publisher; clients refetch workspaces after PATCH
- special handling of `default_workspace` in GET/POST /config
- the stray FS_PERMISSION_DENIED mapping on session routes
- the session picker label, the doctor check, the extra stty exclusion,
  the moved-default resume hint, and the SDK path/status methods

Fix three gaps found along the way:
- clearing the location left `path` in config.toml, so it came back on
  reload; drop the section instead
- treat an empty or relative XDG_CONFIG_HOME as unset
- honor HostProcessOptions.timeout so a stalled PowerShell lookup ends

* refactor: drop the --default-workspace CLI flag

No CLI user needs it yet. Desktop and web reach the default workspace
through the server, so the flag, its resume hint, and the SDK's
ensureDefaultWorkspace() go away along with their changesets.

* refactor: drop the default workspace settings endpoint

The location is now changed only by editing default_workspace.path in
config.toml, which the config watcher picks up without a restart. Remove
GET/PATCH /api/v1/default-workspace and the engine's status() and
setCustomPath(). Session creation keeps mapping the unavailable error to
40930 with { path, reason }, and the reason list moves to the
POST /sessions docs.

* fix: require a drive or UNC share for a Windows default workspace path

Rooted paths such as \Chats resolve against the server's current drive,
so the same setting could point at different folders. Treat them as
invalid_path instead.
2026-10-19 12:29:51 +08:00
Kimi Agent
4a82a07f08
docs: add review scope rules to AGENTS.md (#4265)
Some checks are pending
CI / release-workflow-tests (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
* docs: add review scope rules to AGENTS.md

* docs: verify current code before suppressing resolved threads

---------

Co-authored-by: kimi-agent-bot <317908118+kimi-agent-bot@users.noreply.github.com>
2026-10-18 02:38:34 +08:00
liruifengv
18c6d64272
feat: notify the agent of external changes after /reload (#4019)
Some checks failed
CI / release-workflow-tests (push) Has been cancelled
CI / build (push) Has been cancelled
CI / test (1) (push) Has been cancelled
CI / test (2) (push) Has been cancelled
CI / test (3) (push) Has been cancelled
CI / test (4) (push) Has been cancelled
CI / test (5) (push) Has been cancelled
CI / test-pi-tui (push) Has been cancelled
CI / test-vscode-legacy (push) Has been cancelled
CI / test-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / typecheck (push) Has been cancelled
Nix Build / Check flake.nix workspace sync (push) Has been cancelled
Nix Build / nix build .#kimi-code (push) Has been cancelled
* feat: notify the agent of external changes after /reload

* refactor: route watch-based AGENTS.md change alerts through the change notifier

* test: pin the missed detection of trailing AGENTS.md content deletions

* fix(agent-core-v2): anchor change-notifier comparisons to delivered beliefs

* fix(agent-core-v2): diff the full subagent model pool in change notifications

* fix(agent-core-v2): mute stale-session auto notifications during session reload

* chore(agent-core-v2): regenerate manifests and complete notifier stubs for the reload fixes

* chore: update the reload-change-reminders changeset

* test(agent-core-v2): cover the announced-then-deleted AGENTS.md sequence

* fix(vis): cover the changeNotifier.snapshot wire record

* fix(agent-core-v2): harden change-notifier beliefs for legacy wires and edge baselines

* fix(agent-core-v2): unmute the stale notifier when a session reload fails midway

* fix(agent-core-v2): seed change-notifier beliefs from the rendered snapshot

* fix(agent-core-v2): await the change-notifier snapshot dispatch

* fix(vis): harden the change-notifier snapshot renderer for legacy records

* test: isolate the reload e2e from the watch channel and tighten seed assertions

* chore(agent-core-v2): regenerate the wire manifest for optional belief fields

* chore: drop the changeset for reload change reminders

* fix(agent-core-v2): diff reload reminders against persisted beliefs first

* fix(agent-core-v2): recompute the bound subagent allowlist on catalog changes

* fix(agent-core-v2): roll back change-notifier beliefs on conversation undo

* feat(agent-core-v2): inline added profile metadata in subagent change reminders

* fix(agent-core-v2): detect legacy AGENTS.md truncation and gate skill reminders

* fix(agent-core-v2): reset change-notifier beliefs on context clear

* feat(kap-server): project the reload session action into the OpenAPI document

* fix(node-sdk): keep plugin-only reloads from refreshing workspace catalogs

* fix(agent-core-v2): gate and filter subagent change reminders

* fix(agent-core-v2): evaluate reminder gates against the persisted binding

* fix(kap-server): scope reload catalog refreshes to the target workspace

* fix(node-sdk): scope reload catalog refreshes to the target workspace

* fix(agent-core-v2): reset change-notifier beliefs on compaction

* fix(agent-core-v2): hash AGENTS.md files from one atomic snapshot

* fix(agent-core-v2): close first-watch and legacy gaps in change detection

* fix(kap-server): block reload during compaction and reconcile after failed reload

* fix(node-sdk): block reload during compaction and reconcile after failed reload
2026-10-16 15:15:57 +08:00
Kimi Agent
8fcd3326e7
fix(tui): fold previews only when collapsing saves rows (#4248) 2026-10-16 13:28:52 +08:00
Haozhe
6e7cc909da
feat(agent-core-v2): let dangerous_command_guard=false disable all built-in guard ask policies (#4250)
* feat(agent-core-v2): let dangerous_command_guard=false disable all built-in guard ask policies

* docs(agent-core-v2): name git control-path read relaxation and scope the only-ask-rules claim
2026-10-16 13:23:18 +08:00
Haozhe
ef727e5179
feat(remote-control): support chunked streaming transfers up to 100 MiB (#4214)
Some checks are pending
CI / release-workflow-tests (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
2026-10-15 19:41:19 +08:00
qer
c1459a6184
fix(server): run agent hooks in the session's working directory (#4242)
Agent-level hooks such as PreToolUse, UserPromptSubmit, Stop and PreCompact,
plus hooks fired from the event bus, did not pass a cwd, so the runner fell
back to the directory the engine was started from. Session-level hooks
already used the session directory, and the hooks documentation says the
working directory is the session's project directory. A server hosting
several workspaces, or a CLI that changes directory after the engine starts,
ran these hooks in the wrong place.
2026-10-15 19:38:24 +08:00
7Sageer
85077a4190
fix: align subagent tool descriptions with availability (#4066)
* fix: align subagent tool descriptions with availability

* chore: add subagent tool availability changeset

* fix: align unrestricted subagent media tool descriptions

* fix: gate subagent dynamic tool descriptions by model support

* fix: remove per-step tool activation refresh

* fix: preserve registered tools across availability changes

* chore: revert unintended oxlint auto-fixes from merge commit

* test: trim redundant tool availability description cases
2026-10-15 19:18:13 +08:00
Kai
da5918c0c8
fix(agent-core-v2): nudge the agent to keep its todo list current (#4239)
* fix(agent-core-v2): nudge the agent to keep its todo list current

- Remind only while the list still has pending or in_progress items, and
  drop the first-use arming gate so compaction and /undo no longer arm the
  reminder for agents that never used TodoList.
- Remind after 5 steps without an update (was 10) with text that names the
  step count, progress, and the item still in progress, instead of the
  gentle "ignore it if not applicable" wording.
- Replace the static TodoList write echo with a next step for the current
  list state.
- Drop the churn warnings that discouraged updates from the TodoList
  description, say the list is a live progress panel, and add a TodoList
  paragraph to the system prompt when the tool is active.
- Track todo_list_written, todo_reminder_shown, and todo_turn_ended.

* fix(agent-core-v2): address todo reminder review feedback

- Ask the agent to mark the last open item done only once it is finished;
  if it stays blocked or unfinished, keep it in_progress and say what
  remains in the reply.
- Emit todo_turn_ended for turns that cleared the list, so cleared lists
  count toward the stale-list ratio instead of being dropped.
2026-10-15 17:14:41 +08:00
Rick
034117338c
fix(vscode): add back navigation when AskUserQuestion (#4186) 2026-10-15 16:27:13 +08:00
7Sageer
5bab748ddd
feat(tui): auto-generate session title after the first turn (#4200)
* feat(tui): auto-generate session title after the first turn

* Update tui-auto-session-title.md

Signed-off-by: 7Sageer <sag77r@hotmail.com>

* feat(tui): gate auto session title behind a tui.toml auto_session_title toggle

---------

Signed-off-by: 7Sageer <sag77r@hotmail.com>
2026-10-15 15:31:02 +08:00
liruifengv
9f0693becb
feat(oauth): parse unified /models schema for managed Kimi Code models (#4209)
* feat(oauth): parse unified /models schema for managed Kimi Code models

* fix(oauth): treat absent reasoning metadata as non-thinking
2026-10-15 15:10:54 +08:00
tpoisonooo
60adab4c32
docs(tower): add description (#4216)
* docs: add Tower user guide

* docs: clarify Tower benefits and dependency gates

* docs(tower): add guides

* fix(docs): accept review advices

* docs(tower): remove keep_alive_on_exit

---------

Co-authored-by: konghuanjun <konghuanjun@moonshot.ai>
2026-10-15 12:56:05 +08:00
Kimi Agent
b2603264ec
fix(google-genai): map thinking effort off to LOW for Gemini 4 models (#4230)
* fix(google-genai): map thinking effort off to LOW for Gemini 4 models

Gemini 4 supports only LOW/MEDIUM/HIGH thinking levels and always thinks;
sending MINIMAL for effort=off makes every request fail with a 400. Degrade
'off' to LOW (thoughts still hidden) for gemini-4 models in both the
agent-core-v2 requester and the legacy kosong provider, keeping MINIMAL for
Gemini 3.

Co-authored-by: 7Hanrui <qihanrui@moonshot.ai>

* fix(google-genai): drop comment in comment-free agent-core-v2 source

Co-authored-by: 7Hanrui <qihanrui@moonshot.ai>

* fix(google-genai): preserve effort off in thinkingEffort for Gemini 4

LOW with suppressed thoughts is the Gemini 4 encoding of 'off', so map it
back to 'off' in the thinkingEffort getter instead of reporting 'low'.

Co-authored-by: 7Hanrui <qihanrui@moonshot.ai>

* fix(google-genai): keep explicit LOW kwargs reported as low on non-Gemini-4

Only Gemini 4 encodes 'off' as LOW with suppressed thoughts, so gate the
reverse mapping on the model; a caller-supplied LOW/includeThoughts=false on
other models keeps reporting 'low'.

Co-authored-by: 7Hanrui <qihanrui@moonshot.ai>

* fix(google-genai): report LOW as low in thinkingEffort again

Gemini 4 encodes 'off' as LOW with suppressed thoughts, which is
indistinguishable from an explicit LOW/includeThoughts=false kwarg, so no
reverse mapping can serve both callers. Nothing in the repo reads this
getter to persist or display effort, so keep the derive-from-kwargs
semantics; for Gemini 4's 'off', 'low' is the honest report of what runs.

Co-authored-by: 7Hanrui <qihanrui@moonshot.ai>

* fix(google-genai): reject thinking effort off for Gemini 4 models

Gemini 4 supports only LOW/MEDIUM/HIGH thinking levels and always thinks,
so requesting effort 'off' now fails fast with a clear thinking-config
error (matching the always-reasons rejection other protocols already use)
instead of sending an invalid MINIMAL level or silently degrading to LOW.

Co-authored-by: 7Hanrui <qihanrui@moonshot.ai>

---------

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
Co-authored-by: 7Hanrui <qihanrui@moonshot.ai>
2026-10-15 12:34:28 +08:00
Haoyang Ma
20b59915bb
fix(google-genai): use thinking level for Gemini 4 models (#4208)
* fix(google-genai): use thinking level for Gemini 4 models

The thinking parameter is picked by a hard-coded `gemini-3` name check, so
Gemini 4 model ids fall through to `thinkingBudget`, which the Gemini API
rejects with HTTP 400 ("Thinking budget is not supported for this model.
Use thinking level instead."). Add `gemini-4` to the same check in both the
engine copy and the legacy kosong provider; Gemini 3 and earlier keep their
current encoding.

* chore(changeset): keep the Gemini 4 entry to the user-facing outcome

* test(google-genai): use the real Gemini 4 model id in the thinking tests

---------

Co-authored-by: Selene <mahaoyang@corp.netease.com>
2026-10-15 11:21:44 +08:00
Kimi Agent
d4b9dc4a2d
docs(changelog): sync 2.2.0 from apps/kimi-code/CHANGELOG.md (#4223)
Some checks are pending
CI / test-vscode-legacy (push) Waiting to run
CI / release-workflow-tests (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
* docs(changelog): sync 2.2.0 from apps/kimi-code/CHANGELOG.md

* docs(changelog): restore notify_user feature entry and document fullscreen enablement

* docs(changelog): simplify notify_user enablement to /experiments panel

* docs(changelog): drop non-public KIMI_CODE_TRUST_WORKSPACE entry

* docs(changelog): drop one-line title from notify_user entry

---------

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
2026-10-15 00:15:53 +08:00
Kimi Agent
a9e764db61
chore: sync release 2.2.0 back to main (#4222)
* feat(kap-server): add remote control device deletion (#4192) (#4195)

* feat(kap-server): add remote control device deletion

* fix(kap-server): coordinate with the local tunnel before deleting this machine's device

Co-authored-by: liruifengv <liruifeng1024@gmail.com>

* ci: enable recoverable publishing for the October release (#4218)

* ci: publish core releases from isolated release branches

* ci: simplify release recovery to the CLI package

* ci: publish VS Code from approved release commits

* test: await release test registration for type-aware lint

* test: avoid assuming order of independent tower events

* ci: limit release migration to existing publishing flow

* chore: sync web dist from code-app (#4221)

* chore: sync web dist from code-app

code-app: f828bac439ab5b9266ff8387c2afb96ecfcb59ae

* ci: retrigger (flaky rpc-events teardown ENOTEMPTY)

---------

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>

* ci: release packages (#4220)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: qer <wbxl2000@outlook.com>
Co-authored-by: liruifengv <liruifeng1024@gmail.com>
Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-10-15 00:14:11 +08:00
qer
d1c3b048fd
ci: publish core releases from isolated release branches (#4217)
* ci: publish core releases from isolated release branches

* ci: simplify release recovery to the CLI package

* ci: publish VS Code from approved release commits

* test: await release test registration for type-aware lint

* test: avoid assuming order of independent tower events

* ci: limit release migration to existing publishing flow
2026-10-14 22:35:59 +08:00
Haozhe
f28c51c01f
feat(agent-core-v2): add global default for deferred MCP tool disclosure (#4210)
* feat(agent-core-v2): add global default for deferred MCP tool disclosure

* feat(agent-core-v2): capture the deferred MCP default at server connect time
2026-10-14 17:19:29 +08:00
grapedge
83a39b49ed
perf(tui): stop blocking the footer on git status (#4201) 2026-10-14 15:08:59 +08:00
7Sageer
0327e8e9a8
feat: support model migration metadata (#4171)
* feat: support model migration metadata

* chore: revert web bundle sync

* feat: persist model upgrade metadata

* fix: resolve model upgrade targets

* fix: keep model upgrade metadata consistent

* fix: complete model upgrade metadata handling

* fix: handle aliased upgrade targets and RFC3339 variants

* fix: resolve bare model upgrade targets

* feat: prompt for model migration in the TUI

* fix(tui): defer model migration until the editor is idle

* fix(tui): preserve model migration prompts and preferences

* fix(tui): hold the model migration prompt while /new replaces the session

* fix(tui): keep the resume cache hint from replacing an open dialog

* fix(tui): keep the thinking effort across a model migration when supported

* fix(tui): strip terminal control sequences from migration notices

* fix(tui): warn about prompt cache loss before a mid-conversation migration

* docs: drop the effort persistence claim from the migration wording

* test: trim redundant migration test cases

* fix: switch to the declared replacement when a registry drops the default model

A registry retires a model by dropping it after declaring `upgrade`, but
the refresh deleted the alias together with its upgrade metadata and
cleared the default, leaving users without a model and with a misleading
login hint. Refresh and re-import now move a dropped default to the
upgrade target persisted by an earlier refresh, clearing it as before
when that target is gone too. The TUI warns about the switch and moves
the live session off the dropped model once no dialog is open.

* docs: fix the /reload-tui command spelling in config-files

* fix: resolve migration placeholders at import and keep acknowledgements out of tui.toml

Migration text placeholders were only filled in by the TUI, so the model
catalog served raw templates to every other client. The registry import
now stores the final text and the TUI renders it as is.

Migration acknowledgements are display state rather than preferences, so
they now live in model-migrations.json under the data directory instead of
tui.toml; preference saves and acknowledgements no longer rewrite each
other, and /reload has nothing to sync.

Also carry the dropped model's record in the refresh result instead of
snapshotting it in the TUI, give performModelSwitch explicit persistence
modes instead of a boolean-or-mode flag, fold the Markdown notice into the
picker's notice option, and rename waitForLazyCreation to
waitForSessionAssembly now that it also waits for /new.

* refactor(tui): move the shared model switch out of the /model command

performModelSwitch and its helpers became shared once the migration
prompt and the retired-default switch started calling them, yet they
stayed in the /model command module, leaving a controller depending on
command internals. Move them unchanged to tui/utils/model-switch.ts, which
the command module and the migration controller now both import.

* feat: surface retired default model redirects in refresh results and catalog events

A registry-side retirement only existed in the OAuth orchestrator's
in-process RefreshResult, so kap-server's scheduled refreshes redirected
the default model without any client-visible signal. The refresh response
now carries an optional retired_default { from, to, from_model }, mapped
through to the REST refresh endpoints and the global
event.model_catalog.changed broadcast, and mirrored in the klient
contract.

* refactor(tui): consume the engine's provider refresh instead of orchestrating its own

The TUI ran the OAuth refresh orchestrator in-process through its own
persistence host (including a dead v1 fallback), duplicating what the
engine's discovery service already does. KimiHarness now exposes
refreshProviderModels (via the klient facade over
IProviderDiscoveryService), so the TUI deletes its orchestration glue and
reads retired_default from the engine response. Also fix the klient
facade deriving RefreshProviderModelsResponse from the OAuth login
refresh, which hid retired_default from clients.

* feat: move model retirement follow-through into the engine

The discovery service now records retirements, emits onDidRetireModel,
and answers retiredModelReplacement; agent profiles follow a retirement
live and on restore, so the TUI only shows the notice and steers the
session-less selection. The wire retired_default drops from_model in
favor of an engine-resolved from_display_name. Removes the now-dead
supportsAtomicSectionReplace / replaceConfigSections /
removeProviderFromConfig SDK exports (no remaining consumers).

* Update model migration guidance in documentation

Prompt for migration when the TUI editor is idle and switch to the declared replacement when a registry drops the default model.

Signed-off-by: 7Sageer <sag77r@hotmail.com>

* test(oauth): drop the duplicate dropped-default redirect case

---------

Signed-off-by: 7Sageer <sag77r@hotmail.com>
2026-10-14 14:24:01 +08:00
Kimi Agent
7e58f2d241
fix(kimi-code): keep the previous turn's answer visible when a task-notification turn ends (#3799) 2026-10-14 13:29:14 +08:00
liruifengv
b510fa9aec
feat(kap-server): add remote control device deletion (#4192)
Some checks failed
CI / build (push) Has been cancelled
CI / test (1) (push) Has been cancelled
CI / test (2) (push) Has been cancelled
CI / test (3) (push) Has been cancelled
CI / test (4) (push) Has been cancelled
CI / test (5) (push) Has been cancelled
CI / test-pi-tui (push) Has been cancelled
CI / test-vscode-legacy (push) Has been cancelled
CI / test-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
Release / Release (push) Has been cancelled
Publish VS Code extension / Publish VSIX to marketplaces (push) Has been cancelled
CI / typecheck (push) Has been cancelled
Nix Build / Check flake.nix workspace sync (push) Has been cancelled
Release / Deploy docs (push) Has been cancelled
Release / Native release artifact (push) Has been cancelled
Nix Build / nix build .#kimi-code (push) Has been cancelled
Release / Publish native release assets (push) Has been cancelled
* feat(kap-server): add remote control device deletion

* fix(kap-server): coordinate with the local tunnel before deleting this machine's device
2026-10-13 19:58:01 +08:00
oocz
3f0857eb7d
feat(agent-core-v2): register plugin skills under qualified names and relax plugin name validation (#4188)
* feat(agent-core-v2): register plugin skills under qualified names and relax plugin name validation

* docs: document qualified plugin skill names and relaxed plugin name validation

* fix(tui): prefer plugin commands over same-named plugin skill shorthand

---------

Co-authored-by: yuchengzhen <yuchengzhen@moonshot.cn>
2026-10-13 19:41:48 +08:00
STAR-QUAKE
e4c99a3bad
feat(agent-core-v2): distinguish session-unavailable tools and explain select_tools failures (#4190)
* feat(agent-core-v2): distinguish session-unavailable tools in select_tools

* fix(agent-core-v2): explain tool selection failures and repeated guesses

* fix(agent-core-v2): keep failure counts honest in mixed select_tools batches

- Reuse the globalPolicy cache for denial checks instead of bypassing it.
- A successful name now only resets the consecutive-failure streak and
  clears its own failure record; failed names in the same batch keep
  accumulating attempts instead of being masked by sibling successes.

* fix(agent-core-v2): honor tool source in policy checks and announce empty loadable sets

- Evaluate deny globs with the registered tool's real source; only
  unregistered names fall back to the mcp__ prefix inference.
- Keep select_tools callable via the disclosure check so a profile
  allowlist omission no longer mislabels it as policy-denied.
- Announce the empty loadable state once for legacy sessions whose
  last announcement lacks it, then stay silent.
2026-10-13 19:39:31 +08:00
liruifengv
c69bd6c5a0
feat(kap-server): add remote control device management (#4169)
* feat(kap-server): add remote control device management

* feat(remote-control): tag share URLs with the caller's platform source

The share link's from query parameter was hardcoded to kimi_code_cli, so
links created by the desktop app were mislabeled as CLI traffic.

buildRemoteControlUrl now takes the source explicitly and
RemoteControlOptions carries it as urlSource; kap-server threads
hostIdentity.platform through, so desktop hosts produce
from=kimi_code_desktop while CLI hosts keep from=kimi_code_cli.

* fix(kap-server): stop the local tunnel when the current device is deactivated or deleted

The device management routes only called the cloud API. When the target
device is the machine itself, the local tunnel kept running: after the
relay drops it, the client reconnects and re-registers, so the device
came back online (or was recreated after a delete) and the local status
never returned to off.

After a successful cloud deactivate/delete of the current device, the
routes now also disable the local tunnel manager.

* feat(kap-server)!: drop the remote-control device delete route

Device removal is collapsed to a single deactivate verb: the desktop UI
deactivates devices instead of deleting them, so the DELETE
/remote-control/devices/{id} route and the device client's deleteDevice
go away before this API ever ships.

* feat(kap-server): carry the lock holder in the already-running error

The enable route now returns the RemoteControlAlreadyRunningError holder
(pid, local origin, device id, url, started_at) in the error envelope's
details, documented with a details schema, so desktop can render a
structured conflict state instead of the raw message.

* feat(kap-server): expose the lock conflict in the remote control status

The manager now surfaces the holder when its last enable error is an
already-running lock conflict, and GET /remote-control returns it as a
structured conflict field, so clients can present the conflict state
proactively instead of parsing the error message.

* feat(kap-server): resolve the remote control lock conflict live in status

GET /remote-control now re-inspects the machine lock whenever the
manager is off: a live holder is reported as the conflict even without
a prior enable attempt in this process, and a stored conflict plus its
error text are dropped once the holder's process is gone. Panel state
refreshes such as after device deactivation now reflect reality.

* feat(kap-server): wait for the lock holder to release on current-device deactivation

When the deactivated device is the machine's own and the lock is held
by another live process (e.g. a CLI instance whose tunnel the relay is
about to terminate with user_requested), the route now polls the lock
for up to two seconds before responding, so a client's immediately
following status read sees the settled conflict-free state.

* style(kap-server): silence promise-executor-return in lock release wait

* test(remote-control): pass urlSource in the close-reason cases

* feat(kap-server)!: register remote control devices with the host product name

* refactor(cli): source the remote control identity from app constants

* fix(remote-control): make starts cancellable and harden logout cleanup

* fix(remote-control): close the remaining cancellation and invalidation races

* fix(kap-server): sweep remote control cleanup once more after logout

* docs: note the lock-release failure of remote control deactivation

* fix(remote-control): key cloud sessions by credential and settle cancelled starts

* fix(kap-server): block remote control starts during logout and serialize tunnel toggles

* fix(kap-server): gate local starts during current-device deactivation

* fix(kap-server): match active tunnel ids on deactivation and re-clear sessions after logout

* fix(kap-server): serialize Kimi logouts, harden lock cleanup, and whitelist device fields

* fix(remote-control): abort pending handshakes on close and answer logout before tunnel teardown

* fix(remote-control): cancel enables that are still queued behind a pending disable

* fix(kap-server): recognize foreign logout gates and retry post-logout tunnel teardown

* fix(remote-control): verify the machine lock after disable and recheck deactivation

* feat(kap-server): export loadOrCreateServerToken for host token provisioning
2026-10-13 17:40:24 +08:00
grapedge
afd95f64a5
feat(tui): unify skill prompts and steering (#4165) 2026-10-13 12:17:14 +08:00
7Sageer
fed19d24f0
feat(agent-core-v2): report fork request prefix parity in the prompt cache probe (#4179)
* feat(agent-core-v2): report fork request prefix parity in the prompt cache probe

The fork prompt cache probe only reported the child's cache usage, so a low
hit rate could not be told apart between a client-side prefix divergence and
a server-side miss, and the hit rate itself was diluted by the new tail that
can never be cached.

The requester now keeps a snapshot of each agent's last completed turn
request (the tools and system prompt hashes it already records in
llm.request, input tokens and timing). A forked agent captures its parent's
snapshot when it is created and reports tools_match, system_prompt_match,
parent_input_tokens and parent_request_gap_ms with its first request.

* fix(agent-core-v2): clear the parent request snapshot when the context is rewritten

Undo and compaction rewrite the parent context without touching the
non-persisted snapshot, so a /btw fork made before the next turn request
compared against a request whose input the child no longer inherits.

* fix(agent-core-v2): drop stale parent baselines from the fork cache probe

The probe compared the child's first request against the parent snapshot
captured at scope creation, but a parent undo or compaction landing
before the context copy left that snapshot describing a request the
child no longer inherits, and a model switch between the parent's last
turn and the fork compared across cache namespaces that can never share
a prompt cache.

The probe now watches the parent's ContextSpliced/ContextUndone events
and drops the captured snapshot once the parent context is rewritten,
and the snapshot carries the model alias so the comparison fields and
the parent input token baseline are only reported when both sides ran
the same model.

* fix(agent-core-v2): keep the turn request snapshot across conversation undo

Undo only truncates the tail of the parent context, so the request a
/btw fork inherits is still a strict prefix of the request the parent
last cached: the server cache keeps hitting and the snapshot's hashes
stay accurate. Clearing the snapshot on undo threw away a baseline
that was still valid, and made the requester depend on the undo
domain for no benefit. Only compaction rewrites the prefix, so it
remains the sole event that clears the snapshot.

* refactor(agent-core-v2): validate the fork cache probe baseline by context prefix revision

The requester subscribed to ContextSpliced solely to keep a telemetry
snapshot fresh, which made the module understand context rewrites and
grow an event bus dependency for the probe's sake. The probe's own
subscription could not cover forks created after a compaction either,
which is the only reason the requester had to listen at all.

Context memory now exposes a prefix revision that increments on every
deleting splice, the turn request snapshot records the revision it was
taken at, and the probe compares it with the parent's current revision
at probe time. Read-time validation covers both the compact-then-fork
and the fork-then-compact windows with no subscriptions, and the
requester is back to only recording facts about its own requests.

* fix(agent-core-v2): stamp the turn request snapshot with the build-time context revision

The public SDK clearContext path has no busy check and can empty the
parent context while a turn request is in flight. Reading the revision
at completion stamped the snapshot with the post-clear value, so a
later fork saw matching revisions and hashes and silently attributed
the client-side prefix divergence to the server. The request input is
fixed by recordRequest time, so capture the revision in the same
synchronous block; a mid-flight clear then leaves the snapshot on the
pre-clear revision and the probe drops the baseline on comparison.

* fix(agent-core-v2): capture the snapshot context revision where the request messages are copied

The build-time capture still ran after the awaited media resolution,
so a clearContext or compaction landing in that window stamped the
snapshot with the post-rewrite revision for a request whose messages
were copied earlier. resolveRequest is synchronous and copies the
context messages there, so the revision captured alongside the copy
always describes the same context the request was built from.

* fix(agent-core-v2): omit the parent token baseline when the parent request reported no usage

A provider that completes without a usage event left the snapshot with
inputTokens: 0, so a later same-model fork emitted parent_input_tokens: 0
and the input_cache_read / parent_input_tokens analysis divided by zero
or treated an unknown baseline as real. The field is now optional and
absent for that snapshot, which the optional telemetry property already
allows.
2026-10-13 11:15:41 +08:00
7Sageer
cbd754049a
chore: remove unused kaos package and MCP kaos executor option (#4184)
Some checks are pending
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
Publish VS Code extension / Publish VSIX to marketplaces (push) Waiting to run
* chore: remove unused kaos package and MCP kaos executor option

* chore: update nix pnpmDeps hash after kaos removal

* chore: harden resume coalesce key against legacy kaos arguments and condense changesets

* chore: strip legacy kaos options before forwarding session RPCs

* chore: drop ssh2 overrides left unused by kaos removal
2026-10-12 18:43:56 +08:00
Kai
c15638b0a1
fix: cancel in-flight video uploads when media reads are interrupted (#4183) 2026-10-12 17:02:18 +08:00
Kai
0a3a2fbafa
feat: add NotifyUser progress display to desktop and web (#4159)
* feat: show NotifyUser progress in desktop and web

Give NotifyUser a one-line title, report the latest update on the
session status, and forward subagent updates to the parent so GUI
clients can show them on subagent cards.

* feat: turn on NotifyUser progress updates by default

Flip the notify_user flag default to true; the flag stays as the opt-out
(`[experimental] notify_user = false` or KIMI_CODE_EXPERIMENTAL_NOTIFY_USER=0).
Register the new subagent.update wire record in the vis renderers and
record-type union so the manifest coverage test passes.

* refactor: trim NotifyUser surfaces to conversation progress rows

* feat: make NotifyUser title optional and enforce single-line titles

* feat: make NotifyUser opt-in via the settings lab

* docs: describe NotifyUser as off by default with the settings lab opt-in
2026-10-12 17:01:36 +08:00
Haozhe
7f0ff53c8a
fix(remote-control): exit the web server when the relay takes the device offline (#4182)
* fix(remote-control): exit the web server when the relay takes the device offline

* test(cli): satisfy the remote-control handle contract in tui web tests
2026-10-12 16:30:56 +08:00
Haozhe
c151d5a3d0
feat(agent-core-v2): add KIMI_CODE_LLM_HEADERS_TIMEOUT_MS for llm headers timeout (#4092)
* feat(agent-core-v2): add KIMI_CODE_LLM_HEADERS_TIMEOUT_MS for llm headers timeout

* fix(agent-core-v2): harden KIMI_CODE_LLM_HEADERS_TIMEOUT_MS proxy fallback and range
2026-10-12 13:51:39 +08:00
tpoisonooo
c9f01f0738
refactor(tower): coordinate missions with deterministic orchestration (#4074)
Some checks failed
CI / build (push) Has been cancelled
CI / test-pi-tui (push) Has been cancelled
CI / test-vscode-legacy (push) Has been cancelled
CI / test (2) (push) Has been cancelled
CI / test (3) (push) Has been cancelled
CI / test (4) (push) Has been cancelled
CI / test (5) (push) Has been cancelled
CI / test-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / typecheck (push) Has been cancelled
Nix Build / Check flake.nix workspace sync (push) Has been cancelled
Release / Release (push) Has been cancelled
Publish VS Code extension / Publish VSIX to marketplaces (push) Has been cancelled
CI / test (1) (push) Has been cancelled
Release / Native release artifact (push) Has been cancelled
Release / Publish native release assets (push) Has been cancelled
Nix Build / nix build .#kimi-code (push) Has been cancelled
Release / Deploy docs (push) Has been cancelled
* feat(tower): coordinate missions with deterministic orchestration

* fix(tower): disable goal mode

* feat(tower): degrade gracefully on tower state loss

When .tower/comms is deleted while .tower/ survives (e.g. git clean),
tower tools no longer hard-fail with not-initialized:

- TowerStatus returns a state-lost report; never-initialized repos
  (no .tower/ at all) keep the existing not-initialized behavior
- TowerSend/TowerComplete recover a minimal state (directory skeleton,
  empty missions/roster, recoveredAt marker, base taken from the
  current checkout branch) and keep delivering; a caller whose roster
  entry was lost is re-registered as a placeholder named after its
  agent id
- TowerComplete degrades explicitly after a loss: the report is
  delivered to the tower as a completion-report-state-lost message and
  no mission is marked completed
- TowerMerge/TowerRebase and every other locked mutation fail with an
  explicit state-lost error instead of silently running against an
  empty history
- the recoveredAt marker is shown on the TowerStatus dashboard and in
  the status summary, reminding the tower to report the history loss
  to the user

* feat(tower): veto destructive bash commands in the tower main checkout

* fix(tower): allow git clean dot pathspecs inside tower worktrees

* fix(tower): restore attachment guidance for mission context

* fix(tower): engage bash guard only while the workspace has an owner

* fix(tower): veto git clean only with force and -x/-X; drop markInboxRead

* chore(tower): drop per-fix changesets to keep a single concise one

* fix(tower): check tower owner before preparing the user base

* feat(tower): show a notice when goal activation ends tower mode

* fix(tower): unify the mode-mutex exit reason across goal, plan, and swarm

* refactor(tower): drop token stamping from protocol artifacts

* fix(agent-core-v2): deny tower workers subagent delegation

Remove the Agent tool and the subagents allowlist from the tower-worker
profile so workers and reviewers cannot nest subagents inside a mission;
nested subagents bypassed the tower concurrency budget and the tower's
steering. Drop the now-unreachable reviewer-only Agent-resume veto and
its tests; the branch-lease and foreground-resume vetoes stay.

* test(tower): stub ILogService in every AgentTowerService test scope

The fork-restore tests build second DI scopes that register
AgentTowerService without stubbing ILogService, leaving this.log
undefined. When reconcileForeignTower fires a fire-and-forget exit and
the ownership release rejects, the rejection handler's this.log.warn
throws a TypeError that surfaces as an unhandled rejection in the full
suite. Add ix2.stub(ILogService, stubLog()) to all nine scopes that
lacked it, matching the existing sibling pattern.

---------

Co-authored-by: konghuanjun <konghuanjun@moonshot.ai>
2026-10-10 19:28:09 +08:00
HydrogenE7
3395f5bea6
fix: show shutdown progress and force exit on Ctrl+C during shutdown hooks (#4164) 2026-10-10 16:24:36 +08:00
7Sageer
f0bc988bbc
fix(agent-core-v2): keep fork subagent request prefix identical to parent (#4152) 2026-10-10 16:12:20 +08:00
Kimi Agent
72fc1d0a33
fix(tui): show Working… in the status spinner while thinking (#4160) 2026-10-10 15:16:37 +08:00
grapedge
e5b4b88ba9
fix: report cumulative survey user turns (#4156) 2026-10-10 14:25:06 +08:00