Commit graph

265 commits

Author SHA1 Message Date
github-actions[bot]
472192c34c
ci: release packages (#4220)
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
Release / version (push) Has been cancelled
Release / candidate (push) Has been cancelled
Release / vscode (push) Has been cancelled
Release / Release (push) Has been cancelled
Release / Native release artifact (push) Has been cancelled
Release / Publish native release assets (push) Has been cancelled
Release / deploy-docs (push) Has been cancelled
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-10-14 23:25:04 +08:00
qer
c1ec37251e
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>
2026-10-13 20:55:09 +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
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
liruifengv
5b93669767
feat(kap-server): add allow_ignored_globs to fs:list for un-ignoring named paths (#4058)
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
* feat(kap-server): add allow_ignored_globs to fs:list for un-ignoring named paths

The list filter keeps gitignored entries hidden unless they match the
new allow_ignored_globs request field, letting callers surface
specific ignored paths (e.g. .tmp) while the rest of gitignore still
applies.

* docs: document allow_ignored_globs in the fs:list API reference

* fix: traverse ignored ancestor directories of allow_ignored_globs matches

A nested allow glob such as ignored-dir/keep.txt or ignored-dir/** used
to be unreachable in recursive listings because the ignored parent was
skipped before any child could match. Keep an ignored entry when it is a
literal-prefix ancestor of an allowed glob (directories only), and
document that dot-path allowances additionally require show_hidden.

* fix: match ignored ancestor directories across wildcard glob segments

The literal-prefix check still dropped ancestors when a directory
segment of an allow glob contained a wildcard, e.g. ignored-*/keep.txt
or ignored-dir/**/keep.txt. Decide reachability by consuming the
candidate path segment-wise against a prefix of the glob instead.

* fix: correct and harden workspace fs glob matching

Compile **/ to (?:[^/]+/)* so recursive wildcards preserve path
segment boundaries; a/**/b no longer matches a/xxb. This affects
include_globs, exclude_globs, and allow_ignored_globs across
fs:list / fs:search / fs:suggest / fs:grep.

Match glob prefixes iteratively in globCanMatchBelow so deeply
segmented globs cannot exhaust the call stack.

* chore: add changesets for allow_ignored_globs and the glob boundary fix

* fix: satisfy noUncheckedIndexedAccess in the glob prefix grid

* fix: restrict globstar segment expansion to whole path segments

foo**/keep.txt regressed when **/ gained segment-boundary semantics:
the stars sat mid-segment but were expanded as a whole-segment
globstar. Only expand **/ when the stars open a path segment, treat
mid-segment stars as an ordinary within-segment wildcard, and keep a
trailing ** matching across segments as before.

* fix: match workspace fs globs with picomatch and probe speculative ancestors

Replace the hand-rolled glob compiler with picomatch, the standard
engine already used elsewhere in the package, which settles segment
boundary, mid-segment globstar, and deep-pattern complexity edge
cases for good. An ignored directory kept only as a possible ancestor
of an allow glob is now probed (depth and entry capped, fail-open) and
withheld when no descendant actually matches.

* fix: cast readonly glob list for picomatch isMatch

* fix: parse globs whole in the ancestor check and share the probe budget

Splitting allow globs on '/' corrupts brace and extglob constructs
that contain slashes; take path segments from picomatch.scan instead
and fall back to a conservative answer for opaque single-token globs,
letting the descendant probe decide visibility with whole-pattern
matching.

Probe budgets are now shared across one fs:list request instead of
resetting per candidate directory, so a tree full of speculative
ancestors cannot multiply filesystem operations.

* fix: tolerate empty globs and slash-bearing alternatives

picomatch throws on empty patterns where the old compiler simply
never matched, turning previously valid requests into server errors;
filter them out up front. Brace and extglob alternatives that embed
a slash inside one scanned part now fall back to the conservative
ancestor answer as well, leaving visibility to the whole-pattern
descendant probe.

* fix: disable picomatch negation in workspace fs globs

A leading exclamation mark was a literal character in the old
matcher, so exclude_globs like !foo only matched a path literally
named !foo; as a picomatch negation the same request would exclude
everything except foo. Pin the prior semantics with nonegate.

* fix: scan allowance globs with nonegate and skip empty segments

The scan call still used default negation, stripping a literal
leading bang from allowance prefixes like !foo/keep.txt. Consecutive
separators produced empty scanned segments that made picomatch throw
during prefix compilation; empty segments now simply match nothing.

---------

Co-authored-by: qer <wbxl2000@outlook.com>
2026-10-08 18:21:54 +08:00
Haozhe
f409caa21e
fix(agent-core-v2): clear inherited cron tasks at the fork record (#4083)
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 / Native release artifact (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (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
Fork copies the wire journal, so cron tasks persisted as cron.add
records were inherited by the fork and fired from both sessions.
Fold the forked marker record into the cron actor: the task table is
cleared at the fork point and a one-time cron_fork_cleared reminder is
delivered (tracked by a durable forkNotice flag confirmed via
ContextAppendMessage), mirroring the goal feature's fork handling.
The forked event class moves from features/goal to
session/agentLifecycle so both features share it.
2026-09-29 19:10:48 +08:00
Haozhe
06ebfc821e
fix(agent-core-v2): fold UserPromptSubmit hook output into the prompt message (#4081)
* fix(agent-core-v2): fold UserPromptSubmit hook output into prompt content parts

UserPromptSubmit hook messages now merge into the user prompt message as
meta-marked text content parts (contentType text/xml, source 'user prompt
submit hook') at content position 0 instead of a standalone hook_result
user message, so one prompt always yields exactly one user message and
turn pairing can no longer shift. Structured hook JSON without a message
field (e.g. {"continue":true}) no longer injects anything; plain-text
stdout still falls through. turn.prompt records, TurnStarted prompts,
fold turn openings, and steer content keys all strip hook parts; existing
wires with standalone hook_result messages keep their current behavior.

* feat(agent-core-v2): keep UserPromptSubmit hook parts in turn records and handle them across client surfaces

* feat(agent-core-v2): meta-mark bundled skill parts and replace positional slicing

Bundled skill blocks are now constructed with meta { source: 'skill
activation' }, matching the hook-part convention. Every former
content.slice(skillActivations.length) site — turn prompt text, steer
merge/echo, session and fork titles, transcript fold, TUI replay — now
annotates then filters by meta, so prompt content no longer depends on
block positions and the loop needs no hook-part knowledge. A shared
annotate step keeps legacy wires working: leading unmarked blocks (one
per bundled activation) are marked on read before filtering.

* feat(agent-core-v2): strip hook parts from the public TurnStarted prompt at construction
2026-09-29 17:24:09 +08:00
7Sageer
1f6f0b1fa2
feat: trust workspace via KIMI_CODE_TRUST_WORKSPACE env var (#4059)
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
* feat: trust workspace via KIMI_CODE_TRUST_WORKSPACE env var

* fix: honor trust env override in MCP registry and untrust route

* test: add getEnv to mcpManagement bootstrap mock

* test: fold trust-env route case into existing workspaces suite

* fix(cli): mention KIMI_CODE_TRUST_WORKSPACE in the print-mode MCP trust warning

* docs: describe KIMI_CODE_TRUST_WORKSPACE by its semantics, not its MCP effect
2026-09-28 17:03:52 +08:00
tpoisonooo
09af3b483f
feat(tower): interrupt tower wake turns on user input and harden tower operations (#3998)
- tower mode: a message sent while the agent is running aborts the in-progress inbox-wake turn and runs as its own turn; notification-seeded turn waiters now settle launched/completion
- TowerTeardown: keeps worktrees of live agents (not overridable with force), supports exclude and dry_run
- tower roster: died/revived store writes are guarded to the active tower session and attributed with session+pid; agents stopped by the user are marked dead by intent with no revival nag, and unintended deaths get diagnose-first guidance
- workers must TowerInbox before marking a mission completed: the store refuses completion with unread inbox messages, and the briefing carries the inbox-before-completion, mission re-read, and long-operation chunking instructions
- tower store: state.json read-modify-write is serialized with a cross-process lockfile (token-checked release) and written atomically via per-writer tmp + rename

Co-authored-by: konghuanjun <konghuanjun@moonshot.ai>
2026-09-28 12:35:58 +08:00
Haozhe
c7dd84124a
feat: turn filesystem watch back on by default (#4015) 2026-09-24 14:50:10 +08:00
7Sageer
929403b6db
revert: roll back workspace trust-boundary hardening (#4013)
* revert: roll back workspace trust-boundary hardening

Roll back the hardening added in #3964 that guarded against malicious
content inside an already-trusted repository:

- background git invocations no longer override repo-local git config
  (fsmonitor, hooksPath, filters, drivers, gpg, editor)
- agent file tools no longer re-resolve paths through symlinks
- project-local local.toml applies without workspace-trust gating,
  additional_dir entries are no longer rejected for resolving to the
  home directory or filesystem root, and writing it is auto-approved
  again inside a git worktree

Kept, since they only affect the pre-trust window or the trust prompt
itself: the fail-closed trust prompt and lazy footer git detection.

* Update revert-trust-boundary-hardening.md

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

---------

Signed-off-by: 7Sageer <sag77r@hotmail.com>
2026-09-24 14:49:36 +08:00
Haozhe
b3212fd9ab
fix(remote-control): pick credential slot and relay from login region (#3969)
* fix(remote-control): pick credential slot and relay from login region

Global login stores tokens in kimi-code-env-*.json and should use
code-rc.kimi.ai; Remote Control always read kimi-code.json and
code-rc.kimi.com. Resolve both from the persisted oauth ref.

* fix(telemetry): skip the dead global collector and keep shutdown alive

The global collector host has no DNS. Drop it from the region profile and
skip the send instead of falling back to the mainland endpoint. Keep the
shutdown timeout timer referenced so a failed flush cannot exit before the
TUI hands the process to the foreground server.

* fix(remote-control): require explicit relay origin and drop hardcoded .com defaults
2026-09-23 18:10:47 +08:00
Luyu Cheng
895e9d9b86
fix: restore swarm members from persisted lifecycle events (#3970)
* fix: restore swarm members from persisted lifecycle events

* test(agent-core-v2): register subagent lifecycle records in the wire vocabulary

* chore(agent-core-v2): regenerate the wire manifest for subagent lifecycle records

The manifest inventory drives the vis wire-renderer coverage check, so vis gains a renderer for each new record type and treats them as timeline-neutral in the context projector.

* fix(transcript): associate a folded subagent with the task registered after its spawn

Some emitters register the task after publishing the spawn, so the durable
spawn record carries no task id and the cold fold keyed the member by its
agent id. A later task.started then created a second task that no subagent
terminal event ever reached, leaving a duplicate stuck in the running state.
Folding task.started now records the agent-to-task association the live
projector keeps, and terminal subagent records update both representations
when both are retained.

* fix(transcript): restore subagent token usage when folding a completed member

The durable subagent.completed record carries the member's token usage and the
live projector copies it onto the task, but the cold fold dropped it, so a
reopened conversation showed a completed member without usage metadata. The
fold now validates the payload's four counters and restores them.

* fix(kap-server): base the lost-member decision on the turn that spawned it

The cold snapshot only terminalised an unfinished foreground member when the
parent agent was idle, so a member left behind by a restart stayed marked as
running forever once the user started a new parent turn before backfill.
The restored agent refs already name the tool call that spawned each member,
so the decision now uses the turn owning that call: a member is lost when its
own loop is not running and its spawning turn is not the turn the parent is
running now.

* fix(transcript): adopt the spawn placeholder into the task registered afterwards

A spawn published before its task is registered — the Tower worker path —
carries no task id, so the fold created a placeholder keyed by the agent id
and the later task.started added a second task under the registered id. Only
the registered task was ever terminalised, and the detached placeholder was
skipped by the lost-member pass, so a restored transcript kept a duplicate
worker shown as running forever. task.started now folds the placeholder into
the registered task instead of leaving it behind.

* fix(kap-server): drain the live wire before reading a cold snapshot

The append log buffers records and writes them in batches, which is why its
own reader flushes the log first. The cold transcript reads the wire file
directly and skipped that drain, so a snapshot could stop on a stale prefix.
When the transcript binding is created after a turn has already ended, the
whole store is built from that snapshot and nothing repairs it afterwards,
leaving the turn's last tool call without its result and its member marked
lost. Reading now drains the live agent's wire first, as session export
already does before it reads the same files.
2026-09-23 14:25:40 +08:00
tpoisonooo
f7012aa23b
feat(tower): enforce protocol invariants and deny AgentSwarm (#3976)
* feat(tower): enforce protocol invariants and deny AgentSwarm in tower mode

- split missions by functional boundary and workload; simplify spawn briefings
- flip completed missions back to active on non-clean reviews and brief respawns with review history
- refuse completed with open tasks or zero-diff build branches; cap review rounds at 5 with a task_drop escape hatch
- name the next step in review/merge/status tool results; flag unspawned missions in TowerStatus
- veto AgentSwarm execution while tower mode is active
- deflake kap-server catalog test: waitForServerState timeout 3s to 10s

* fix(spawnTool): remove striction

---------

Co-authored-by: konghuanjun <konghuanjun@moonshot.ai>
2026-09-23 13:00:32 +08:00
7Sageer
6451f1e056
fix: harden workspace trust boundaries across git, file tools, and the local web server (#3964)
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
* fix(kap-server): reject malformed and null Origins

isOriginAllowed conflated an unparseable Origin header with an absent
one and allowed both, so a sandboxed document (Origin: null) passed the
WebSocket upgrade check and had its Origin echoed by the CORS hook.
An absent Origin is still allowed for non-browser clients, but a
present Origin that fails to parse, is null, or uses a non-http(s)
scheme is now rejected: the WS upgrade responds 403 and the CORS hook
withholds Access-Control-Allow-Origin.

* fix(kimi-code): sync web bundle for kimi_origin query gating

* fix(agent-core-v2): gate workspace local.toml behind trust and tighten additional_dir

* fix(agent-core-v2): block symlink escapes in agent file tools

* fix: harden background git invocations against repo-local config

* fix(agent-core-v2): close trust-gate gaps in add-dir and additional_dir validation

* fix: neutralize repo-configured clean and process filters in hardened git calls

* fix(agent-core-v2): fail closed when a path is too deep to verify

* fix: probe worktree-scoped filter config in hardened git calls

* fix: fail closed when git filter discovery fails and cache probes for repo subdirectories

* fix(agent-core-v2): block symlink aliases of the project-local config in write tools

* fix: neutralize smudge, merge drivers, and repo-controlled commit signing in hardened git calls

* fix: expand included git configs when discovering repo-defined drivers

* Revert "fix(kimi-code): sync web bundle for kimi_origin query gating"

This reverts commit cd6af49cf1dfebe505f0e890453c3207a74d3e80.

* fix: keep git hardening fail-closed on includes and probe failures in scanners

* fix: fail closed on uncodable driver names and disable repo-controlled signature verification

* fix: neutralize repo-controlled editors and match include sections case-insensitively

* fix: probe config names only and reject dangling symlinks in file tools

* fix: fail closed when core.worktree escapes the repository

* fix(agent-core-v2): match project config paths across separators and case

* fix: arm footer git only after workspace trust persists

* fix(agent-core-v2): check resolved sensitive targets for absolute outside paths

* fix: only skip git config caching for actual include sections

* refactor: share git config hardening primitives between agent-core-v2 and the CLI

* fix(agent-core-v2): clear trusted additional dirs synchronously on trust revocation

* fix(agent-core-v2): compare resolved write targets with Windows path semantics

* fix: fail closed when the git directory disappears during hardening probes

* refactor: move shared git hardening primitives into @moonshot-ai/git-hardening

* fix: close symlinked-gitdir and submodule-recurse gaps in git hardening

* fix(agent-core-v2): reject home-directory ancestors as additional_dir roots

* fix: compare core.worktree with Windows path semantics

* fix: skip git config probes on renders after a negative repo detection

* fix: resolve gitfile pointers against the .git file directory and match includeIf sections

* test: drop duplicated symlink and plain-file cases covered elsewhere

* fix: only treat project-config writes as aliased when the lexical path misses the config pattern

* test: move the realpath guard matrix into a module test

* test: cover git-hardening primitives in the shared package

* refactor: inline git hardening helpers and drop the shared package

Keep the constants and parsers next to the async engine spawn path and
the sync CLI spawn path instead of a third workspace package.

* refactor: drop footer git trust gate and config probing

Workspace trust is a process-level decision, so the TUI never mounts
the footer until the user has trusted. Footer git status now uses
static hardening flags only.

* refactor: route git execution through IGitService.runGit

- Add runGit(cwd, args, options) to IGitService as the public door for
  running git with repo-local config hardening applied.
- GitService implements runGit using the existing hardenedGitConfigArgs
  helper; status/diff now delegate to it.
- collectGitContext drops its own spawn/probe logic and calls
  IGitService.runGit instead, receiving the service through the
  promptPrefix context.
- Tower keeps its own git() function (accepted gap).

* refactor: move git hardening helpers to app/git/hardening

* Revert "fix(kap-server): reject malformed and null Origins"

This reverts commit b799a21d0390ff0e4e66437f0d7b90c0b8171efe.
2026-09-22 21:30:34 +08:00
liruifengv
994287acb3
fix(session): inherit titleKind for default fork titles (#3974)
Some checks are pending
CI / test-windows (push) Waiting to run
CI / lint (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 / 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
2026-09-22 13:34:50 +08:00
liruifengv
6a52dd781b
feat(config): add auto_session_title config option (#3962)
* feat(config): add auto_session_title config option

* chore: drop changeset, changelog entry ships with kimi-code-app instead
2026-09-21 19:55:40 +08:00
liruifengv
b428bfd004
feat(transcript): include step timing and usage in cold-folded steps (#3938)
* feat(transcript): include step timing and usage in cold-folded steps

* refactor(transcript): carry only TTFT and stream duration in cold-folded steps

* refactor(transcript): rename step timing field to llmTiming
2026-09-21 19:14:53 +08:00
HydrogenE7
6a214b85e5
fix(kap-server): avoid stack overflow when caching large wire files (#3957) 2026-09-21 16:31:04 +08:00
Haozhe
f17a22ebf4
feat: turn off filesystem watch by default (#3931)
* feat: turn off filesystem watch by default

* test: enable filesystem watch explicitly in watch-dependent suites
2026-09-19 20:17:47 +08:00
Haozhe
9df7a9ccfb
fix: keep turn ids above the wire-wide max and fold cold transcripts over the active branch (#3922)
* fix(agent-core-v2): floor the human turn clock at the wire-wide max on engine journal reset

* fix(kap-server): fold the cold transcript snapshot over the restorable branch chain

* fix(agent-core-v2): advance the human turn clock when a turn starts

* fix(kap-server): split reused wire turn ids in the live transcript projector

* fix(kap-server): adopt the completed cold tip for mid-turn attach events

Continuation deltas after a lazy transcript attach belong on the last
cold turn, not a newly split export id.
2026-09-19 17:47:22 +08:00
Haozhe
2502d2157f
revert(kap-server): drop the flat entity message protocol (v3 WS + history API) (#3532) (#3920)
This reverts 64505e36e3.

The v1 WS + legacy REST + transcript surfaces are alive on main and remain
the single protocol surface; kimi-inspect returns to the transcript-based
data model (keeping #3747's removal of the prompt input, which adapted to
the agent-core-v2 prompt-queue fold).
2026-09-19 12:40:31 +08:00
liruifengv
2cedfaf125
fix(kap-server): deliver session-level interaction events past agent filters (#3901) 2026-09-19 12:05:34 +08:00
liruifengv
92c3c59b22
feat: expose resolved base_url on models.dev catalog provider items (#3909)
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 / Publish native release assets (push) Blocked by required conditions
Publish VS Code extension / Publish VSIX to marketplaces (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
2026-09-18 20:43:06 +08:00
Grapedge
3cc6b2a330
feat(kimi-code): carry turn trace id and copilot stats in rating surveys (#3907) 2026-09-18 19:49:19 +08:00
Haozhe
60f2a63278
fix(agent-core-v2): reuse the queued prompt id for a single steer (#3906)
* fix(agent-core-v2): reuse the queued prompt id for a single steer

A follow-up sent during a turn minted a second context id, so cancel
while the model was still requesting could show the same text twice
and make the host prompt un-undoable. Reuse the queued prompt id when
one prompt is steered, mark that user as in-turn so undo targets the
host turn, and project it as a non-anchor origin for the client.

* fix(agent-core-v2): type in-turn steer origin on the human prompt

The human PromptOrigin type rejected the inTurn field, which failed
typecheck/build and left the generated state manifest stale.
2026-09-18 18:56:08 +08:00
7Sageer
b0d0a80c32
feat: add usage telemetry for swarm, tower, external hooks, and remote control (#3897)
* feat(agent-core-v2): add tower_mode_enter telemetry for tower mode entry

* feat(agent-core-v2): add swarm_mode_entered/exited telemetry

* feat(agent-core-v2): add external_hook_resolved telemetry

* feat(agent-core-v2): add tower_mode_exit telemetry

* feat(kap-server): add remote_control_toggle telemetry

* fix(agent-core-v2): exclude aborted hooks from failure count and track tower entry errors

* fix(agent-core-v2): keep decorated params contiguous in ExternalHooksRunnerService

* fix(kap-server): classify failed remote control disables in telemetry

* fix(kap-server): ignore stale tunnel errors when disabling an already-off remote control

* fix(kap-server): distinguish a failed concurrent startup from a disable failure

* refactor: slim telemetry event payloads and outcome branches

* refactor: inline remote-control tracking and drop redundant event properties

* refactor: tighten hook failure filter and remote-control test fake

* fix(agent-core-v2): count hook spawn and wait failures in failed_count
2026-09-18 18:36:02 +08:00
Haozhe
73ebe9ab2f
fix(transcript): attach promptIds to cold-folded steer frames (#3896)
* fix(transcript): attach promptIds to cold-folded steer frames

* chore(changeset): note cold-folded steer frames after reload
2026-09-18 16:37:33 +08:00
Haozhe
53e5e3fca6
fix(agent-core-v2): pair steered follow-ups by reserved message id (#3891)
Reserve the context message id when a prompt is steered, emit turn.steer only after that message is appended, and join live/cold transcript plus fork by the id instead of content.
2026-09-18 16:05:27 +08:00
HydrogenE7
5108cad9b6
perf: speed up session resume and session index on large workspaces (#3889)
- engine: single-pass wire restore, deferred immer freeze during replay,
  concurrent task-file reads, O(1) token-counting/file-history folds
- sdk: windowed tail-read replay fold overlapped with engine restore
- kap-server: incremental wire cache for transcript reads, bounded-concurrent
  user-messages fan-out, search sync fingerprints and capped passes
- session index: O(1) by-id lookup, dir-mtime freshness signals,
  incremental cold prepare, session_index.jsonl compaction
- cli: deduplicate the user skills watcher
2026-09-18 15:05:23 +08:00
7Sageer
c5ad17f06a
feat(agent-core-v2): support api_key_env for provider credentials (#3762)
* feat(agent-core-v2): support api_key_env for provider credentials

Providers can declare api_key_env = "VAR" in config.toml to read their
Bearer token from an environment variable instead of storing it inline.
The value is resolved per request (rotation-friendly); an unset or empty
variable fails with config.invalid naming the provider and variable.
apiKey+apiKeyEnv and apiKeyEnv+oauth are rejected as conflicts.

The /models refresh path resolves the same chain (inline apiKey ->
apiKeyEnv -> env sub-table); a provider whose variable is unset lands in
failed[] without affecting others, and open-platform providers keep the
env declaration instead of persisting the resolved secret.

Custom registries: applyCustomRegistryProvider consumes the api.json env
field — imported providers get apiKeyEnv, the legacy inline apiKey is
dropped, and a hand-edited apiKeyEnv survives refreshes (tracked via
source.envKey). kimi provider add --api-key and the TUI registry token
field are now optional so public registries import without a key.

* docs: document api_key_env provider credentials

* fix(oauth): preserve hand-edited apiKeyEnv on registry refresh and address review nits

* fix(oauth): validate apiKeyEnv conflicts during refresh and address review nits

* fix(oauth): mirror apiKeyEnv in the klient provider contract and harden refresh validation

* fix(oauth): stop auto-binding registry env names to provider credentials

* fix(oauth): preserve hand-edited apiKeyEnv across registry re-imports

* fix(oauth): scope apiKeyEnv preservation to the owning registry

* fix(agent-core-v2): preserve apiKeyEnv across models.dev catalog re-imports

* fix(kap-server): drop apiKeyEnv when the provider update route receives a replacement key

* fix(agent-core-v2): replace provider credential fields on TOML writeback

* fix(kap-server): normalize whitespace-only api_key in the provider update route

* refactor(oauth): unify provider credential rules into shared primitives

A new provider-credential module in the oauth package owns the credential
precedence chain, the mutual-exclusion conflicts, the user-facing messages,
and the write-side tri-state reconciliation; the refresh orchestrator,
agent-core-v2 (model-auth, catalog, auth readiness), and the kap-server
provider routes compose it instead of re-deriving the rules per layer.

applyOpenPlatformConfig now takes credential: {apiKey}|{apiKeyEnv} and
merges onto the existing record, so open-platform refreshes no longer drop
hand-written fields (customHeaders, the env sub-table) on the inline-key
path either, and the refresh's write-then-undo block is gone.

Registry imports converge on removeCustomRegistryEntries +
applyCustomRegistryEntries (prior-snapshot provenance): the exported
capture/restore helpers are gone, the CLI persists a re-import with a
single setConfig instead of per-id removeProvider RPCs, and
default_model/default_provider survive a re-import whenever they still
resolve. kap-server's importCustomRegistry keeps the purge-then-rewrite
two-phase replace the config service's raw-merging writeback requires.

kap-server create/replace routes accept api_key_env (tri-state, mutually
exclusive with api_key), and GET /config plus the provider catalog item
expose the binding. A declared-but-unset api_key_env now fails readiness
checks with config.invalid (was auth.token_missing), matching request-time
behavior. Registry 401/403 without a key prints an authentication hint.

* fix(cli): persist registry re-import removals on both harness generations

The v2 harness's setConfig deep-merges per domain (retaining omitted keys
and skipping undefined defaults), so a shrunk re-import left removed
providers and aliases in config.toml and kept a cleared default dangling.
The CLI and TUI registry flows now share persistRegistryImport: on v2 the
removal phase and the rebuilt records go out as two atomic
replaceConfigSections writes (the writeback merges alias fields from raw
TOML, so the purge must be persisted first); on v1 the removeProvider RPC
cascades the removals before one merge write. defaultModel/defaultProvider
snapshots are captured before any removal so the restore works on both
paths.

* fix(oauth): reject oauth before the legacy env fallback and persist cleared thinking on re-import

refreshProviderModels' env sub-table fallback now throws the same
apiKey+oauth conflict the chat path rejects, instead of authenticating
with the fallback key and rewriting the provider to drop oauth.

persistRegistryImport writes the cleared thinking section through the
replacement payload, and drops the v1 fallback branch — registry imports
always persist through replaceConfigSections, so the removal phase no
longer needs per-id removeProvider RPCs.

* chore: consolidate provider credential changesets into one entry

* chore: trim changeset to the api_key_env entry

* fix: harden provider credential status and registry imports

* fix(oauth): expose browser-safe provider credential rules

* fix(node-sdk): replace serialized provider credentials

* fix(oauth): reject credential conflicts during refresh

* fix: harden custom registry re-imports

Reject reserved provider collisions and credential endpoint drift before mutation. Replace registry-owned sections atomically with compare-and-set guards, and carry the replacement contract through klient and node-sdk.

* refactor(registry): centralize custom registry import ownership

Route CLI and TUI imports through the engine via the typed SDK and Klient operation. Keep registry replacement policy inside the engine and preserve credential edits made while fetching the registry.

Cover the shared entry point with real configuration storage and memory/IPC transport tests.

* test: trim redundant api_key_env and registry-import coverage

* fix(cli): reuse the stored registry key on keyless re-import

Both first-party clients encoded "no key given" as an empty string, but
the engine's fallback chain (options.apiKey ?? registryKeyFromExisting)
only reuses the key parked in the provider's source blob when the option
is undefined. A keyless re-import of a private registry therefore went
out without an Authorization header and failed with 401 from the CLI
and the TUI dialog, while the kap-server REST route (which passes
undefined) reused the stored key fine.

Pass undefined from the CLI handler and the TUI import dialog instead
of normalizing to ''. The dialog's result type now marks apiKey
optional, matching the engine contract.

* test: pin CAS rejection and credential-conflict behavior

The coverage trim went past redundancy in three places, leaving the
PR's headline guards untested. Restore the compare-and-set rejection
path (guarded value changed on disk -> retry error, no write) and the
absent-section guard normalization in config.test.ts, the
apiKey+apiKeyEnv / apiKeyEnv+oauth conflict rejections at runtime
resolution (modelAuth) and at the refresh orchestrator (discovery,
with per-provider failure isolation), and the open-platform refresh
through api_key_env proving the resolved secret never lands in the
provider record. Also add the first direct unit tests for the shared
declaredProviderCredential / reconcileProviderCredentialUpdate
primitives.

* refactor(oauth): share reserved provider id rules between import and refresh

* Delete .changeset/registry-import-concurrent-credentials.md

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

* test: trim cross-layer duplicate registry and credential coverage

---------

Signed-off-by: 7Sageer <sag77r@hotmail.com>
2026-09-17 22:02:53 +08:00
qer
bd06178913
fix(kap-server): avoid duplicating steered prompt content (#3853)
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 / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Publish VS Code extension / Publish VSIX to marketplaces (push) Waiting to run
* fix(kap-server): rebuild chat transcript after undo

* test(kap-server): provide undo registry in broadcaster fixtures

* fix(kap-server): preserve non-anchor steers through undo

* fix(kap-server): rebuild undo transcript after persistence completes

* test: complete restored notification origin fixture

* fix(kap-server): keep original prompt when steering

* chore: add changeset for steered prompt content fix

* fix(kap-server): keep restored prompt content after late projector attach

* fix(kap-server): prefer store prompt content after transcript backfill
2026-09-17 01:14:35 +08:00
Grapedge
0cf413f775
fix(kap-server): open a new turn for abort-reissued steers in cold transcripts (#3844) 2026-09-16 19:34:02 +08:00
7Sageer
da31c472a2
feat(agent-core-v2): add skill scopes and mark custom-theme as tui-only (#3843)
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
* feat(agent-core-v2): add skill scopes and mark custom-theme as tui-only

Builtin skills can now declare a scopes whitelist (tui | web); skills
without scopes stay visible everywhere. The value is carried through
SkillSummary, the klient RPC contract, and the kap-server REST wire,
and the TUI slash commands filter by it. HTTP clients (code-app) drop
skills whose scopes exclude their own UI mode, so TUI-only skills like
/custom-theme no longer leak into app/web.

* fix: filter scoped skills from the acp and vscode palettes

ACP slash commands and the VS Code GetSlashCommands handler also
project SkillSummary lists; both now drop skills that carry a scopes
restriction so tui-scoped skills stay out of non-tui clients.
2026-09-16 19:14:22 +08:00
Luyu Cheng
41eac5d2e7
feat(kap-server): keep client metadata on prompts and skill activations (#3764)
Store the optional metadata object on prompt submission and skill activation as opaque client metadata on the user or skill-activation origin, carry it through prompt events, the transcript projector, snapshots and history rebuilds, and echo it on prompt items without adding it to model content. Use display_text entries for session titles, undo labels and fork titles when every entry provides one. Project user turn payloads, live and rebuilt, through a path-free projection.
2026-09-16 17:56:43 +08:00
qer
cafd9b5a65
fix(kap-server): rebuild chat transcript after undo (#3837)
* fix(kap-server): rebuild chat transcript after undo

* test(kap-server): provide undo registry in broadcaster fixtures

* fix(kap-server): preserve non-anchor steers through undo

* fix(kap-server): rebuild undo transcript after persistence completes

* test: complete restored notification origin fixture
2026-09-16 17:15:35 +08:00
Luyu Cheng
1c7e996aa8
fix(kap-server): record user slash skill activations steered into a running turn (#3832)
Accept skill_activation origins with a user-slash trigger in onTurnSteered so a slash command sent while a turn is running gets a transcript frame, and keep those frames from draining a queued prompt's id. Project origin file attachments onto steered frames on both the immediate and deferred paths, matching onTurnStarted and the history rebuild.
2026-09-16 17:10:44 +08:00
tpoisonooo
8660a07b3a
fix(tower): subagent cards still showing "completed" during rework (#3833)
Co-authored-by: konghuanjun <konghuanjun@moonshot.ai>
2026-09-16 16:20:24 +08:00
Luyu Cheng
402ee71c1a
feat(kap-server): accept text parts in skill activation attachments (#3831)
Widen activateSkillAttachmentSchema so the attachments array accepts text parts alongside image, video and file, letting a caller interleave text and media in the order the model should read them. Schema only; the route already resolves attachments as WireContent.
2026-09-16 14:02:08 +08:00
HydrogenE7
7d174ac933
perf(agent-core-v2): evict completed subagent scopes behind an LRU cache (#3778)
* perf(tui): batch and cache agent swarm progress rendering

* perf(agent-core-v2): evict completed subagent scopes behind an LRU cache

* fix(agent-core-v2): stop the agent actor in the session machine when its scope is removed

* fix(agent-core-v2): emit a terminal event for the final rate-limited run and defer eviction while background tasks run

* fix(agent-core-v2): include in-flight retries when abandoning suspended agents

* fix(agent-core-v2): roll back the closing flag when scope removal fails and wait per the configured eviction timeout

* fix(agent-core-v2): terminalize subagents spawned after batch cancellation and report task timeouts as failures

* chore: restore upstream/main state of files mangled by lint-staged autofix in the merge commit

oxlint --fix rewrites (prefer-set-has, catch-error-name, prefer toSorted/.at(-1)/toReversed)
touched seven files the branch never modified; one of them (oauth managed-kimi-code.ts)
no longer typechecks. Restore all seven to their exact upstream/main state. Committed
with --no-verify so the same autofix does not re-mangle them.

* fix(agent-core-v2): retry deferred scope evictions without exhausting the attempt budget, dedupe terminal events for starting retries, and patch-level the changeset

* fix(agent-core-v2): finish scope teardown instead of reactivating a partially torn-down scope

* fix(agent-core-v2): terminalize subagent-start hook cancellations and re-acquire resume targets after metadata reads

* fix(tui): record cancelled background agents in the transcript

* fix(agent-core-v2): route mirror terminal events through the batch exactly-once guard

* fix(tui): guard terminal swarm members from re-cancellation and deliver terminal status to cancelled foreground subagent cards

* fix(agent-core-v2): classify eviction as removed when teardown already closed the scope

* Merge remote-tracking branch 'upstream/main' into perf/subagent-scope-eviction

Skip lint-staged for this merge: its oxlint --fix pass rewrites unrelated files
(prefer-set-has etc. mangled seven files in the previous merge commit), while the
merge content is upstream's lint-clean code plus conflict resolutions already
verified by oxlint.

* chore: restore upstream/main changes dropped by a stash roundtrip during the merge

A git stash/pop cycle used to isolate an unrelated flaky test reverted 82 files of the
merge result to the pre-merge branch state, so commit 375ff2a4a missed them. The
working tree already held the correct merged content; this commit restores it.

* fix(agent-core-v2): propagate the cancellation reason from turn abort to tool signals

Cancelling a turn aborted the turn's llm scope and every tool scope
without a reason, so tools and subagents only ever saw the default
AbortError and could not tell a user cancellation from a system abort.
With the swarm terminal-event classification this surfaced as
`subagent.failed` ("This operation was aborted") on Ctrl+C instead of
`subagent.cancelled`.

Carry the reason end to end: `MachineEngine.abort(reason)` sends it on
`input.abort`, the agent machine remembers it for the turn and forwards
it to `turn.abort` and to every tool scope it aborts, the turn machine
passes it to the llm scope, and the loop service hands its cancellation
(a `UserCancellationError` by default) to the engine.

* fix(agent-core-v2): stop rebuilding an evicted subagent after its caller aborts

`createAgentAwaitingClose` polled for the previous scope to finish
closing without ever looking at the caller's abort signal, so cancelling
an `Agent` or `AgentSwarm` resume during that wait still recreated the
scope afterwards. In the `Agent` path the run then rejected before any
terminal event was mirrored, leaving an idle scope that the scope cache
no longer tracked.

Thread the caller's signal into the helper and check it before every
attempt; the Agent tool passes its call controller and the swarm service
passes the attempt signal. Also trim the eviction changeset to the one
sentence the changeset rules ask for.

* fix(agent-core-v2): report task-manager aborts of a subagent as cancelled

When the task manager times out or stops a background subagent it aborts
the run with a plain reason ('Timed out', the TaskStop reason), and the
run rejects with that raw reason. The task manager therefore classifies
the task as timed_out or killed, but the mirror only recognised
`UserCancellationError` as a cancellation and emitted `subagent.failed`,
so the transcript recorded a failure before the authoritative
`background.task.terminated` event could land.

Classify a terminated run by the shape of its abort reason: a real
Error that is not an AbortError (the swarm's own per-item timeout) stays
a failure, everything else that aborted the run is a cancellation. The
swarm's start-failure path uses the same rule.

* fix(agent-core-v2): flush the wire before evicting a subagent scope and re-pick LRU candidates

Two gaps in the scope-cache eviction pass:

- `AgentLifecycleService.remove()` swallows a failed wire flush and still
  tears the scope down, so an eviction that hit a disk-full or transient
  I/O error would drop the in-memory scope and let a later resume rebuild
  from a stale wire. Flush the agent's wire explicitly before removing;
  if that fails, keep the scope resident and retry on a later pass. The
  idle and task checks are repeated after the flush so a resume that
  started meanwhile is not cancelled by the removal.
- The pass snapshotted its candidates up front and re-validated them by
  attempt count only, so a scope that was resumed and completed again
  while an earlier eviction was awaited kept matching with attempts 0 and
  was evicted despite now being the most recently used. Pick the oldest
  eligible entry from the live map on every step instead, skipping only
  the entries this pass already tried.

---------

Co-authored-by: Kaiyi <me@kaiyi.cool>
2026-09-15 20:33:24 +08:00
Kimi Agent
39a74556a6
fix(plugins): rename WebBridge display name to Kimi Browser Extension (#3803)
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
* fix(plugins): rename WebBridge display name to Kimi Browser Extension

The product has renamed WebBridge to Kimi Browser Extension in work and
Chrome. Update the user-facing display name across the built-in
capability entry, TUI plugins selector, managed plugin manifest,
marketplace catalog, skill docs, and user docs to match. Internal ids,
binary names, CDN paths, and daemon references are unchanged.

* fix(plugins): bump webbridge to 1.11.4 and keep legacy docs anchor

Address review: point the changeset at the scoped CLI package, bump the
renamed plugin's manifest/catalog/docs version so installed users are
offered the renamed package as an update, and preserve the published
#kimi-webbridge documentation anchor beside the renamed heading.

* docs(plugins): match only the known extension-update error messages

Broadening the version-mismatch trigger to the generic prefix 'Please
update the' would misclassify unrelated tool errors as an outdated
browser extension; match the two known full messages instead.

---------

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
2026-09-15 18:13:51 +08:00
liruifengv
bb0c66a15b
feat(oauth): switch the managed usage payload to the quota model (#3787)
The platform /usages payload now serves per-window used ratios
(goods_version, a usages map of limit5h/limit7d/monthTotal/monthCode
entries with used_ratio/reset_time, and boosterWallet) instead of
absolute used/limit rows.

- oauth: parse and fetch the quota model; keep the platform helpers
- toolkit / agent-core-v2 / node-sdk: getManagedUsage returns the quota
- kap-server: /oauth/usage passes the camelCase quota shape through
  (the legacy snake_case wire is gone)
- TUI /usage: plan rows are presence-driven from the quota payload;
  the monthly row carries a kimi/code breakdown line
- docs: server-api reference updated for the new response shape
2026-09-15 13:33:20 +08:00
HydrogenE7
f2486241fb
perf(agent-core-v2): shard the session event bus by agent id (#3775)
* perf(agent-core-v2): shard the session event bus by agent id

* fix(agent-core-v2): preserve full-stream-before-typed ordering in agent channels and render perAgent counts in the inspector

* fix(agent-core-v2): deliver agent full streams before session typed handlers and dispose sharded channels with the bus

* fix(agent-core-v2): prevent rebuilding agent channels after the event bus is disposed

* fix(agent-core-v2): isolate agent channels on generation replace and keep typed handlers on the shared per-type channel

* fix(agent-core-v2): require the active lifecycle context before firing an agent full-stream channel

* fix(agent-core-v2): reject stale lifecycle contexts when subscribing to an agent full-stream channel

* fix(agent-core-v2): honor the agent context in typed subscribeAgent subscriptions
2026-09-15 12:18:20 +08:00
tpoisonooo
0725ef1ce0
fix(agent-core-v2): tower mode mistaking newly agents for previous name (#3752)
* fix(agent-core-v2): resolve tower roster identities to the latest registration

Agent ids restart from agent-0 in each session, so a freshly spawned
worker collided with the previous session's roster entry and every
find-first lookup (caller identity, write guard, death bookkeeping)
resolved to the stale entry: workers read the wrong inbox, sent under
the wrong name, and were denied their own writes, mission updates, and
reviews.

- resolveAgent picks the latest roster entry for an agent id; all
  callers (resolveCallerName, write guard, resume veto, died/revived)
  go through it
- registerAgent retires same-agent-id entries before appending
- enter() (/tower on) now adopts the workspace roster itself instead of
  relying on a manual TowerInit

* fix(agent-core-v2): adopt the tower roster when a replayed tower mode finds a dead foreign owner

A forked or restored session replays the durable TowerModeEnter into an
active tower mode without ever calling enter(), so the roster adoption
added there never ran on the restore path: with the previous owner
session gone, the fork kept the mode (and the stale roster) until a
manual TowerInit. The dead-owner branch of the restore-time
reconciliation now adopts the workspace, mirroring enter()'s takeover
of an idle owner; a live foreign owner still causes an exit.

* fix(agent-core-v2): await the outgoing tower owner's release before adopting its roster

Taking tower mode over from a live but idle owner called the owner's
synchronous exit(), whose ownership release ran fire-and-forget, and
immediately adopted the roster — two concurrent load-modify-save cycles
on .tower/comms/state.json that could lose the new owner or resurrect
the stale roster. exit() now awaits the ownership release and the
takeover awaits the owner's exit(); the remaining callers either await
(RPC/HTTP tower-mode-off) or explicitly ignore the promise (mode mutex,
restore-time self-exit).

* fix(agent-core-v2): fail tower activation when the roster adoption cannot complete

Adoption failures (unreadable or unpersistable state.json) were
swallowed into a log warning, so enter() and the stale-owner restore
both activated tower mode with the foreign owner and stale roster still
in place — the exact identity mismatch the adoption is meant to
prevent, now with a false success report. adoptTowerRoster() now throws
a TowerProtocolError with the underlying cause: enter() propagates it
before any tool is activated, and the restore path drops the replayed
tower mode instead (it must not throw inside the restore hook chain).

* fix(agent-core-v2): propagate unreadable tower state during roster adoption

adopt() treated any state.json read failure as an uninitialized
workspace via isInitialized()'s catch-all, so an existing but
unreadable state file (EACCES, EISDIR, transient I/O) reported a
successful no-op adoption and enter() activated tower mode against the
foreign state — bypassing the activation guard added in the previous
commit. Only ENOENT now means uninitialized; every other read error
propagates into the fail-activation / deactivate-on-restore paths.

---------

Co-authored-by: konghuanjun <konghuanjun@moonshot.ai>
2026-09-15 12:03:10 +08:00
qer
1336be3877
fix(kap-server): verify indexed search results against session sources (#3631)
* fix(kap-server): verify indexed search results against session sources

* fix(kap-server): reject unverifiable search source identities

* fix(kap-server): bound search source checks by the query deadline

* fix(search): report sessions skipped during indexing

* fix(search): bound outstanding source identity checks

* refactor(search): group source check coordination state

* test(search): isolate source check limit from background sync
2026-09-14 21:36:33 +08:00
Haozhe
2d4d799ac3
fix(kap-server): omit hidden thinking summaries from v1 session history fold (#3765) 2026-09-14 19:56:55 +08:00
Haozhe
cd0d4a1d3e
fix(agent-core-v2): display reasoning_content over reasoning_details summary in chat completions (#3735) 2026-09-14 19:51:33 +08:00
Haozhe
4623395379
refactor(agent-core-v2): fold the prompt queue into the agent loop service (#3747)
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
* refactor(agent-core-v2): fold the prompt queue into the agent loop service

Delete AgentPromptService/IAgentPromptService: prompt submit/queue/steer/
abort now ride the agent machine queue through IAgentLoopService's extended
surface (submitPrompt/submitSteerPrompt/enqueuePrompt/steerPrompts/
abortPrompt/drainPrompts/injectPrompt/retryPrompt/promptQueue plus
hooks.onBeforeSubmitPrompt and the promptAdmission reservation slot).

Durable prompt.* event classes move to agent/prompt/promptEvents.ts and keep
their registrations; promptAdmissionKey keeps its fold. Dead assets go away:
promptResolutionKey, PROMPT_ALREADY_COMPLETED (kap-server 40903 path),
promptLaunchingKey and clear(). Compaction gating (queue while compacting,
resume on finish) moves into the loop reservation drain.

The 'agentPromptService' wire name keeps its shape: a thin AgentPromptChannel
facade (same decorator id) forwards submit/submitSteer to the loop, so
klient memory/ipc/debug transports and the kap-server dispatcher are
unchanged.

* test(agent-core-v2): re-pin prompt queue semantics on the loop service

Rewrite promptService.test.ts (25 cases, count unchanged) against the real
AgentLoopService with the scripted-LLM harness, fold the launch-window
reservation out of promptQueue().pending to match the old snapshot contract
exactly, and update the debug-channels pin to the facade's submit/submitSteer
surface.

* refactor(agent-core-v2): lint-align the loop prompt queue surface

* fix(agent-core-v2): settle prompt completions on the turn-result chain

Match the deleted service's microtask position: prompt.completed/aborted and
the completion deferreds fire from a result.then chain attached at bind time
instead of synchronously inside endTurn, so wire/emit ordering with
post-turn producers (tool unregister, next-prompt launch) stays identical to
the baseline snapshots. Steered children move onto the reservation so the
chain can settle them after the active turn is gone.

* refactor(agent-core-v2): move the prompt-submit gate into the agent machine

* refactor(agent-core-v2): keep image compression captions inline in prompt messages

* refactor(agent-core-v2): drop the durable prompt admission facility

* refactor(kap-server): resolve prompt auth at turn runtime instead of submit time

* refactor(agent-core-v2): teach the agent machine queue metadata, multi-id steer, gate rewrite, and pause

* refactor(agent-core-v2): converge prompt submission on machine queue user entries

* refactor(agent-core-v2): replace loop prompt records with a waiter registry fed by machine events
2026-09-14 15:07:18 +08:00
liruifengv
6126472c7a
feat(agent-core-v2): graduate AI session titles from experimental (#3749) 2026-09-14 11:53:19 +08:00
Haozhe
7d7e8de80c
refactor(agent-core-v2): rebuild wire persistence and flip agents to session-spawned actors (#3737)
Some checks are pending
CI / test-windows (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 / 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
* feat(agent-core-v2): persist the human runtime mirror as human.* records in the wire journal

Introduce mode-2 coexistence: the machine eventStore journal becomes a
tree-projection-filtered adapter over the same wire file (single writer via
the WireService append queue), the engine switches from memoryJournal to the
file journal with a seed fallback while no human records exist, and cold
readers skip the new record family constructionally. Adds downgrade
round-trip e2e coverage, whitelists agent.switched/context.undone from
unknown-record telemetry, asserts the undo switch triple after flush, and
resets the machine engine after an undo rerun so machine and wire turn
clocks stay aligned.

Squashed from:
refact(agent-core-v2): project wire journal as an in-memory branch tree behind IAgentJournal
refact(agent-core-v2): undo as branch switch with dual-emitted legacy record and restore replay
refact(agent-core-v2): queue late attachments during restore rerun and flatten fork sources to the active chain
feat(agent-core-v2): persist the human runtime mirror as human.* records in the wire journal

* feat(agent-core-v2): add full compaction to the human agent domain

* refactor(agent-core-v2): keep pending input state events out of the wire journal

* refactor(agent-core-v2): flip agent DI scope ownership to session-spawned agent actors

* refactor(agent-core-v2): build the agent wire and blob views in the session layer

* refactor(agent-core-v2): persist human domain records under the agent.* wire namespace

- replace the human. record prefix with an explicit whitelist (AGENT_WIRE_RECORD_TYPES) guarded against the Event2 vocabulary; legacy human.agent.* journals stay readable through a transition prefix
- unknown-type records skipped during restore now go to the log file instead of the console (malformed records still report to the console)
2026-09-13 23:01:45 +08:00