Commit graph

832 commits

Author SHA1 Message Date
7Sageer
51bd52a589
fix(kimi-code): flush wire journals before print-mode exit (#3531)
* fix(kimi-code): flush wire journals before print-mode exit

A print-mode turn's tail records (step.end / turn.ended / prompt.completed)
are dispatched fire-and-forget and reach the journal only through the wire
service's async persist queue. The print cleanup path never awaited that
queue: with telemetry disabled (KIMI_DISABLE_TELEMETRY=1) cleanup returns
in microseconds, and process.exit on the error path cut off the pending
append-log flush, dropping the failed turn's closing records. Flush every
session agent's dispatcher (which awaits the wire persist queue and the
append-log store) before disposing the app, bounded by the shutdown
timeout and best-effort so a persist failure never masks the turn outcome.

* fix(kimi-code): settle each agent's wire flush independently

Promise.all rejects as soon as one agent's flush fails; the best-effort
caller then proceeds to app.dispose() and process.exit while the remaining
agents' flushes are still in flight, re-exposing their journals to the
truncation this cleanup is meant to prevent. Await every flush with
Promise.allSettled instead (matches the drain helper's convention), and
cover it with a two-agent regression test.

* fix(kimi-code): run print-mode shutdown phases concurrently

The wire flush, v2 telemetry shutdown, and v1 telemetry shutdown each hold
a 3s allowance; run sequentially they can take 9s, past the 8s outer
cleanup bound — the caller's process.exit would then cut off the tail
(app.dispose included). The phases are independent, so await them
concurrently (worst case one allowance) while keeping the v2 shutdown
failure propagation and the best-effort semantics of the other two.

* fix(kimi-code): quiesce active turns before the print-mode wire flush

A termination signal (SIGINT/SIGTERM/SIGHUP) can arrive mid-turn: the
cleanup ran the wire flush immediately, while the still-running turn only
produced its cancellation and closing records from dispose()'s
fire-and-forget teardown — after the flush, and after the signal handler's
process.exit. Cancel every session agent's queued and active turns and
await loop idleness before flushing (best-effort, bounded by the shutdown
timeout); idle loops make this a no-op on the normal exit paths. Torn-down
agent scopes are skipped defensively, mirroring the flush's per-agent
settlement.

* fix(kimi-code): drain prompts and await prompt completion in print quiesce

Two follow-ups from review:

- The loop settles (releaseActiveTurn) before the prompt-settle chain
  dispatches prompt.completed, so awaiting loop idleness alone let the
  wire flush race the final record. Quiesce now also drains each agent's
  prompt queue and awaits the tracked prompt completions (registered at
  enqueue time) before the flush runs.

- Restore drainBackgroundTasks to Promise.all: a previous edit
  unintentionally switched it to allSettled alongside the per-agent wire
  flush, silently discarding persistence failures from
  suppressTerminalNotification()/wait(). Only the independent wire
  flushes are meant to be best-effort.

* fix(kimi-code): cover every agent's prompt queue in print quiesce

Tracking only the main run's prompt completion left subagent and
background prompts racing the wire flush the same way: the loop reports
idle before that agent's prompt-settle chain dispatches prompt.completed.
Replace the per-handle completion tracking with a uniform wait — after
draining and cancelling, poll every agent's prompt queue snapshot until
none reports an active or pending prompt. settle() clears the active
prompt and dispatches the record in one synchronous block, so an empty
snapshot proves the record is already queued for the flush.

* fix(agent-core-v2,kimi-code): cover the prompt launch window in print quiesce

A termination signal can also arrive while startNext() is mid-launch: the
prompt has left pending and is not active yet, so drain() cannot cancel it
and an active/pending snapshot reads empty. Quiesce would then flush and
exit while the launch still dispatches records afterward.

Expose the service's launching phase on PromptQueueSnapshot and make the
print cleanup's quiesce a repeat-until-idle loop: every pass drains,
cancels, and awaits the loops, then re-checks launching/active/pending, so
a prompt surfacing from the launch window is cancelled on the next pass
instead of escaping the flush.

* fix(kimi-code): freeze loop producers across the print-mode flush

An empty prompt queue is only a point-in-time observation: background
task completions and cron fires enqueue straight into the loop, bypassing
the prompt queue, so a late producer could still start a turn — and new
records — after the journals were flushed. Quiesce now leaves a
quiescence guard held on every loop once queues read empty; the caller
holds the release across the wire flush and app disposal, so late
submissions queue behind the guard and are rejected by disposal instead
of racing process.exit. Loops that refuse the guard (still busy) send the
quiesce into another drain/cancel/settle pass.

* fix(agent-core-v2): flush the wire journal when removing an agent

AgentLifecycleService.remove() quiesced the agent but never flushed its
wire journal: the records reached the append log only through the
fire-and-forget retirement flush, so a process exiting right after a
subagent's removal (e.g. print mode on a termination signal) could
truncate the closing records. Flush the agent's event dispatcher after
the quiesce and before disposal; a persist failure is reported without
blocking the removal.

* fix(agent-core-v2): wait for the prompt queue to go idle before flushing a removed agent

The remove() flush could still snapshot the persistence queue before the
cancelled prompt's final record was appended: loop.settled() resolves in
releaseActiveTurn() before the prompt-settle chain dispatches
prompt.aborted/prompt.completed, and prompt.drain() does not await that
settlement. Wait (bounded) for the prompt queue to report no launching,
active, or pending prompts before flushing; an unreadable snapshot counts
as idle so a wedged service cannot stall the removal.

* chore: widen the print wire-flush changeset to termination signals

* fix(agent-core-v2): re-cancel prompts that finish launching during removal

A prompt mid-launch (startNext awaiting daemon materialization or a
pre-submit hook) is invisible to drain() and has no turn to cancel yet;
the passive idle wait would then let it run to the deadline and flush
before its closing records existed. Repeat drain/cancel/settle on every
pass until the queue reads idle, and once idle hold a quiescence guard
across the flush and disposal so a late producer cannot start new work
in between.

* fix(kimi-code): stop task producers before the print-mode wire flush

Task termination bypasses both the prompt queue and the loop quiescence
guard: AgentTaskService dispatches TaskTerminated straight to the wire,
and disposal would force-stop still-running tasks after the journals were
already flushed. Stop every session agent's tasks up front in the quiesce
phase (mirroring AgentLifecycleService.remove()), so each task's
termination record is dispatched before the flush instead of racing
process.exit. keepAliveOnExit tasks stay exempt, matching remove().

* fix(agent-core-v2): do not let suppression failure short-circuit stopAllOnExit

A detached task's terminal-notification suppression failing (e.g. the
persist write rejects) used to reject the whole stopAllOnExit before
stopAll() ran, so every task stayed active — and callers settling the
rejection (print-mode cleanup, agent removal) proceeded as if the tasks
were stopped, losing their termination records at exit. Settle each
suppression independently, log the failure, and always stop the tasks.
keepAliveOnExit tasks remain exempt by design.

* chore(kimi-code,agent-core-v2): halve print wire-flush tests and trim comments
2026-09-04 18:31:42 +08:00
qer
eba23edb93
feat(agent-core-v2): drop the experimental gate from turn-level file history (#3525)
* feat(agent-core-v2): drop the experimental gate from turn-level file history

The file_history flag and its KIMI_CODE_EXPERIMENTAL_FILE_HISTORY env
var are removed; first-touch baselines, turn checkpoints, and the
changes/turnRecorded/contentAt reads now run unconditionally, so the
per-turn file diffs served by kap-server no longer depend on opt-in
configuration.

The changes REST response drops its enabled field — recorded alone
tells an authoritative empty result apart from a turn whose records
were never made, lost to a crash, or displaced by retention.

* fix(agent-core-v2): probe blob existence with a stat, not a directory listing

turnRecorded always answered false for turns whose snapshots lived under
the file-history/ prefix directory: BlobStoreService.has listed the
scope directory (a shallow readdir) and exact-matched the nested key
against top-level entries, so keyed blobs were never found and the
changes endpoint reported recorded=false for exactly the turns that had
edits. Stat the key through storage.size instead, and pin the
turn-recorded assertions against a real node-fs home so the harness
covers the production layout.

* fix(agent-core-v2): probe every keyed blob before calling a turn recorded

Merging the start and end entries let an end entry with key null (a
deleted or oversize-at-end file) shadow the start baseline, and probing
only one surviving key missed partial loss in the other phase: a
session displaced from the thirty-session window could still claim
authority for turns whose snapshots were gone. turnRecorded now stats
every distinct keyed blob across both checkpoints and reports the turn
unrecorded when any is missing.
2026-09-04 15:57:59 +08:00
Grapedge
60136588a4
feat(kimi-code): add session rating survey (#3516)
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 / 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
2026-09-04 12:32:24 +08:00
Haozhe
b184b31497
feat(agent-core-v2): drop the dangerous command guard in auto permission mode (#3529)
* feat(agent-core-v2): allow unanalyzable bash commands in auto permission mode

* feat(agent-core-v2): drop the dangerous command guard in auto permission mode
2026-09-04 11:33:11 +08:00
Kai
523d35b54b
fix(agent-core-v2): keep background questions open past turn end and inline their answers (#3522)
Some checks are pending
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 / 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 / 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(agent-core-v2): keep background questions open past turn end and inline their answers

Background AskUserQuestion reused the generic task pipeline end to end, which
broke it in two ways: the pending interaction was still bound to the asking
turn, so it was cancelled the moment the agent finished its turn, and the
turn-end cancel response was then misread as an answer. On top of that the
completion notification only carried a pointer to the task output file,
forcing an extra Read round trip for a few bytes of JSON.

- Detach background question interactions from the asking turn so they stay
  pending until answered, stopped, or the agent closes.
- Treat cancelled interaction responses as dismissals.
- Inline the answer JSON in the question task notification and word the
  notification as answered or dismissed; fall back to the output file only
  when the answer exceeds the inline budget.
- Trim the background launch result to task id, status, and one next step.
- Fold transcript notification summaries before inline answer blocks.

* fix(agent-core-v2): fail background questions on tool errors and translate interaction cancellations in the question service

Follow-up hardening from review:

- The interaction kernel's cancellation response now has a named shape,
  InteractionCancellation, and SessionQuestionService.request translates it
  into a dismissal (null) before handing the result to callers. The
  AskUserQuestion tool no longer inspects answer maps for a cancelled key,
  so a bare answer map can never be mistaken for a cancellation.
- QuestionBackgroundTask settles as failed with the tool's message as the
  stop reason when the question tool reports an error, instead of writing
  the error text as completed output. The generic task notification then
  carries the reason, and the answered/dismissed wording is not used.
- The question notification only says answered or dismissed when the task
  output parses as an answers payload; any other output keeps the generic
  completed wording.
2026-09-03 20:53:09 +08:00
Kai
b199e3326d
feat(agent-core-v2): remind the model of its context budget and point compaction notes at the wire journal (#3423)
* feat(agent-core-v2): remind the model of its context budget and point compaction notes at the wire journal

Add the contextBudget feature: a context_budget reminder that restates used/max/trigger tokens as usage crosses half, three quarters and ninety percent of the compaction trigger, and a compaction_ahead reminder delivered once per window when the trigger is within ten percent of the context window, so the model can persist and verify state while it can still call tools. Both read IAgentFullCompactionService.budget(), which derives from the same CompactionTriggerBudget that drives auto compaction, and both are stripped from the summarizer input.

Behind compaction_recovery_pointer, compaction records the wire journal line range it covered (wireLines on context.apply_compaction, folded into the replayable fullCompaction.wireRanges key) and appends a Context Recovery footer to the model-facing contextSummary with the on-disk wire.jsonl path, every earlier window's line range, and a primer on reading the journal; the UI-facing summary stays the note plus TODO. Read returns wire.jsonl lines under the sessions directory untruncated and spill-exempt so a single record can be read back after Grep locates it, and the compaction instruction tells the summarizer a recovery pointer follows the note.

Both flags default on; KIMI_CODE_EXPERIMENTAL_CONTEXT_BUDGET_REMINDERS=0 and KIMI_CODE_EXPERIMENTAL_COMPACTION_RECOVERY_POINTER=0 disable them. Telemetry gains context_budget_reminder, compaction_ahead_reminder, and ahead_* fields on compaction_finished.

* feat(agent-core-v2): ship context budget reminders and the recovery pointer without flags

- Remove the two experimental flags; both behaviors now ship unconditionally and the compaction instruction carries the recovery note in its template.
- Lower-bound recovery windows at the latest context.clear journal record so a window never points into history the user discarded.
- Add the appended recovery footer's estimated tokens to summaryOutputTokens so tokens_after and the post-compaction token floor stay honest.

* fix(agent-core-v2): cap event log reads and refuse empty-history compaction

- Cap a single wire.jsonl record read at 150k chars, below the window-minus-trigger margin, so one read can never push the context past the model window; the note points at sed | jq for longer records.
- Keep at least the last record when tail-reading the event log instead of returning silently empty output with a contradictory note.
- Fail the compaction when an overflow shrink would drop every message, instead of compacting an empty history and replacing the context with a groundless note.

* fix(agent-core-v2): drop the redundant ninety bucket and soften ahead-reminder wording

- Remove the 90% context-budget bucket: the compaction-ahead threshold is always at or below it, so it only echoed the stronger last-chance reminder moments later.
- Stop suggesting a commit as a way to persist state before compaction; files and the todo list cover it without prompting unwanted commits.
- Make the event-log note's primer reference conditional on a compaction having run.

* chore: merge the compaction changesets into one
2026-09-03 19:26:30 +08:00
7Sageer
ed215c61cb
fix(telemetry): drop null values from flattened event payloads (#3518) 2026-09-03 17:54:19 +08:00
Haozhe
a020946916
refactor(agent-core-v2): remove the staleGuard feature (#3517)
* refactor(agent-core-v2): remove the staleGuard feature

Drop the read-before-edit runtime guard: Edit/Write executions are no
longer vetoed when the target file was never read or its mtime changed
since the last read, and successful Read/Edit/Write no longer refresh a
recorded mtime. Removes the staleGuard replayable state key and the
staleGuard.recorded / staleGuard.cleared durable wire events; old wires
keep replaying through the unknown-type skip path. apps/vis keeps
projecting and rendering those historical records via locally declared
legacy record types.

* fix(agent-core-v2): skip retired wire record types silently during restore

Restore reports every journal record whose type has no registered event
class through onUnexpectedError. Sessions written before the staleGuard
removal can hold a staleGuard.recorded entry per successful
Read/Edit/Write, so loading one floods the log with WireError stacks.
Keep a retired-type list of record types that were once durable
vocabulary; restore skips them without reporting, while genuinely
unknown records stay on the error path.
2026-09-03 17:51:10 +08:00
7Sageer
26dd6ce6ae
fix(telemetry): deduplicate session_started and model switch events (#3499)
* fix(telemetry): deduplicate session_started and model switch events

* fix(telemetry): keep engine session_started for direct v2 SDK clients and avoid model_switch race

* fix(telemetry): preserve model_switch when activation rebinds the same alias

* fix(telemetry): route TUI reload through harness

* test: update /reload message-flow test for harness reload route
2026-09-03 16:49:27 +08:00
Haozhe
ca5cc76211
fix(tree-sitter-bash): recognize heredocs in character-level balanced scanning (#3503)
* fix(tree-sitter-bash): recognize heredocs in character-level balanced scanning

scanBalancedStatements treated heredoc bodies as ordinary characters, so a stray quote, paren, or backtick inside a heredoc body (for example an apostrophe in a PR body passed through a command substitution) broke the scan and produced ERROR nodes; the resulting hasError made dangerous-command-ask judge the whole command unanalyzable and prompt for approval even in yolo mode.

Parse << and <<- delimiters (excluding <<< herestrings) with the same unquoting rules as the token-level heredoc reader, queue pending bodies, and skip them line-wise at newlines. Skip arithmetic $(( ... )) regions via scanBalanced so a left-shift << is never mistaken for a heredoc operator.

* fix(agent-core-v2): raise the bash parse wall-clock budget to 500ms

A 20ms wall-clock budget could abort an otherwise fine parse under CPU contention, GC pauses, or cold-start JIT, flipping the permission verdict to unanalyzable (spurious approval prompts) or silently dropping AGENTS.md re-reminders. Normal commands parse in well under 1ms; maxNodes stays the deterministic cap, and 500ms remains a backstop against pathological parser loops.

* fix(tree-sitter-bash): skip comments and legacy arithmetic during heredoc-aware scanning

The heredoc-aware scan queued a heredoc for any << it encountered, including inside comments (echo $(printf x # <<EOF\n)) and legacy arithmetic expansions (echo $(echo $[x << 2]\n)); both are valid bash that parsed cleanly before, and the regression flipped them to hasError and an unanalyzable permission verdict.

Skip # comments to end of line when the preceding character starts a new word, and skip ${ ... } / $[ ... ] expansions as balanced units (mirroring skipDollar), so << is only recognized where a redirection operator can actually appear.

* fix(tree-sitter-bash): skip word-glued subscripts during heredoc-aware scanning

Indexed assignments such as echo $(a[x<<2]=3\n) put arithmetic inside a word-glued [ ... ] subscript; the heredoc-aware scan read the << shift operator there as a heredoc start, regressing valid bash that parsed cleanly before to hasError and an unanalyzable permission verdict.

Skip a [ ... ] region as a balanced unit when the bracket immediately follows a word character (subscripts and glued glob classes); a bracket at word start keeps the existing character scan, so real heredocs after words (cat foo[ab]<<EOF) and bare [ command arguments are unaffected. The subscript regression is covered by a unit case only: the reference parser splits subscript arithmetic into binary_expression while this parser keeps it an opaque word, a structural difference that predates this change and has no differential fixture yet.

* fix(tree-sitter-bash): skip conditional regions and look through continuations in heredoc-aware scanning

Two more character-scan contexts queued bogus heredocs after the heredoc-aware scan: a [[ ... ]] conditional region (echo $( [[ x == @(<<EOF) ]]\n) and regex right-hand sides such as [[ x =~ <<a ]]), and a # preceded by a backslash-newline continuation (echo $(printf foo\<newline>#bar)), where removing the continuation keeps the hash inside the preceding word instead of starting a comment. Both are valid bash that parsed cleanly before.

Skip word-start [[ ... ]] as a balanced region (a << inside a conditional is never a heredoc operator; a bracket in argument position keeps the character scan), and walk back over \+newline pairs before classifying a # as a comment. The extglob conditional case joins the differential fixtures; the continuation case is unit-only because the reference parser errors on it.

* fix(tree-sitter-bash): scan substitutions as part of heredoc delimiters

A heredoc delimiter containing a substitution (echo $(cat <<$(foo)\nbody\n$(foo)\n)) was truncated at the first paren, so the queued delimiter never matched the body closing line and the scan swallowed the rest of the range, regressing valid bash to hasError and an unanalyzable permission verdict.

scanHeredocDelimiter now scans $( ), ${ }, $[ ], and backtick regions wholesale as part of the delimiter word (recursing with the heredoc-aware statement scanner for $( )), mirroring how bash treats the whole word as the delimiter. The case stays unit-only because unquoted delimiters hit the already-registered heredoc-content-chunks structural difference with the reference parser.
2026-09-03 15:28:11 +08:00
7Sageer
a3b48a7272
fix(kimi-code): honor KIMI_DISABLE_TELEMETRY and restore crash telemetry in v2 print mode (#3498)
* fix(kimi-code): honor KIMI_DISABLE_TELEMETRY and restore crash telemetry in v2 print mode

* fix(kimi-code): attribute v2 print crash telemetry to the resolved session model
2026-09-03 14:57:24 +08:00
Haozhe
20a0ba9b17
test: speed up kap-server suite and exclude minidb from default projects (#3504)
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
* test: speed up kap-server suite and exclude minidb from default projects

* test(kap-server): restore baseline server after sessions tests replace it
2026-09-03 14:32:28 +08:00
7Sageer
ff7ed1cc86
fix(agent-core-v2): track session index mirror give-up event once per failure episode (#3493)
* fix(agent-core-v2): track session index mirror give-up event once per failure episode

The give-up telemetry fired on every failed flush once the consecutive
failure count crossed the threshold, so a session with a persistently
failing mirror reported hundreds of thousands of events per day. Emit
it only when crossing the threshold; the counter resets on the next
successful flush, so a later episode reports again.

* fix(agent-core-v2): latch the mirror give-up event per failure episode

The equality guard missed episodes where unpublished-manifest flushes
(manifest === undefined also increments the counter) pushed the count
past the threshold before the first throwing flush. Latch the report
per episode instead; the latch resets on the next successful flush.
2026-09-03 11:20:07 +08:00
Kai
052e98ec17
fix(agent-core-v2): rebuild persisted subagents when resuming after a restart (#3478)
* fix(agent-core-v2): rebuild persisted subagents when resuming after a restart

Agent(resume=<id>) only consulted the in-memory agent roster, so once a
session was reopened in a new process every persisted subagent id failed
with "does not exist" even though its wire log and metadata were intact.
The resume path now reads the session metadata once, verifies the target
is a subagent owned by the caller, and re-creates its agent scope from
the persisted records when it is not live before running the turn.

* fix(agent-core-v2): sync rebuilt subagents to the caller mode and match rules by their persisted profile

A subagent rebuilt for resume replayed the permission mode it was
spawned with, so a child persisted in yolo kept running in yolo after
the parent had switched back to manual; the rebuild now copies the
caller's current mode the way a fresh spawn does.

Permission rules with a profile subject such as Agent(coder) were
matched against the fallback label while the target was offline,
because only live agents exposed their profile during execution
resolution. Every spawn site now records the profile name in the
subagent labels and the resume path reads it back for display and rule
matching when the agent is not live.

Adds a kap-server e2e case that spawns a subagent, restarts the server
on the same home directory, resumes it through the Agent tool, and
checks that its prior context reaches the next model request.

* fix(agent-core-v2): keep pinned permission modes when rebuilding a subagent for resume

Tower workers are pinned to auto mode at spawn and skipped by the
permission-mode broadcast, but the rebuild path synced every restored
subagent to the caller's mode, so a dead worker recovered through
Agent(resume=...) after a restart lost its pinned mode. The exception is
now a single predicate next to the worker profile, shared by the
broadcast and the rebuild.

* fix(agent-core-v2): record subagent profiles in the lifecycle instead of at each spawn site

The persisted profile name that offline resumes use for display and
permission-rule matching was written by three spawn sites, and the
session-init child was still missing it. The lifecycle now records it
centrally: create() takes the profile from the binding it is given and
fork() takes the override or the source agent's profile, so every
subagent spawn is covered and the spawn sites no longer pass it.

* chore: merge the subagent-resume changesets into one
2026-09-02 23:22:22 +08:00
7Sageer
0faa878f28
fix(agent-core-v2): write the bound model into the ambient telemetry context (#3484)
* fix(agent-core-v2): write the bound model into the ambient telemetry context

* fix(agent-core-v2): restore the ambient telemetry model after profile replay
2026-09-02 21:57:23 +08:00
7Sageer
b6f78f9fc8
Revert "fix(agent-core-v2): assemble flag-gated features after config ready (…" (#3486)
This reverts commit eb4cd4b38e.
2026-09-02 21:43:09 +08:00
Haozhe
c52d583143
docs: remove agent-core-v2, kap-server, and transcript package docs (#3481) 2026-09-02 21:33:58 +08:00
Haozhe
75708925a5
fix(kap-server): stop exiting the process on uncaughtException (#3477)
The process-level uncaughtException handler installed by startServer
called process.exit(1), so a single stray exception killed every
session the process served — and, embedded in the desktop main
process, killed the whole app past the shell's own crash guard. Log
the error at error level and keep serving instead.

createServerLogger gains an optional stream so hosts can route server
logs into their own log channel.
2026-09-02 21:16:58 +08:00
tpoisonooo
8057d30afb
fix(tower): support config.toml configuration (#3461)
* fix(agent-core-v2): rework tower mode enter failures and config-flag assembly

- IAgentTowerService.enter() returns a typed TowerEnterResult: the 4
  former silent failure points now carry their reason (not-main-agent /
  experiment-off / feature-not-assembled / owned-by-live-session with
  the owner session id + title); kap-server and node-sdk map each reason
  to a distinct SESSION_TOWER_MODE_INVALID message via
  towerEnterFailureMessage() instead of one misleading catch-all.
- Fix config-sourced [experimental] tower flag never assembling the
  tower feature: ConfigService seeds its state synchronously at
  construction with a best-effort readFileSync of the config document it
  owns, so the flag is already visible when TowerFeature's constructor
  runs during App-scope creation. No event machinery: a runtime config
  flip updates flag reads but does not re-run feature constructors — a
  restart is required, pinned by test. docs/flag.md + docs/features.md
  document the contract.
- Consolidated changeset for @moonshot-ai/kimi-code.

* fix(tower): release handler when teardown

---------

Co-authored-by: konghuanjun <konghuanjun@moonshot.ai>
2026-09-02 21:16:14 +08:00
7Sageer
eb4cd4b38e
fix(agent-core-v2): assemble flag-gated features after config ready (#3471)
FeatureAssemblyService ran during the eager bootstrap batch, while
ConfigService was still loading config.toml asynchronously, so
flags.enabled() always read false for config-sourced flags and gated
features (e.g. tower via [experimental] tower = true) never assembled.

registerFeature now accepts a { flag } option; gated registrations are
assembled in a deferred pass once IConfigService.ready resolves, and
IFeatureAssemblyService.ready exposes that pass. WorkspaceInstanceManager
.materialize also awaits config.ready so session creation cannot race
the deferred assembly.
2026-09-02 21:09:35 +08:00
7Sageer
9f866cb7f4
refactor(agent-core-v2): rebuild telemetry context as a scope-bound layered registry (#3430)
* refactor(agent-core-v2): rebuild telemetry context as a scope-bound layered registry

* fix(agent-core-v2): prefer ambient model in telemetry envelope and repair print-runner stub

* fix(agent-core-v2): delete only the fragment registered by this telemetry binding

* fix(agent-core-v2): bind telemetry context writes to the binding's own fragment

* fix(agent-core-v2): keep stale telemetry emissions on the binding-owned fragment

* refactor(agent-core-v2): mirror turn-request trace_id into ambient telemetry context

* refactor(agent-core-v2): telemetry key-resolution cleanups

Drop the dead defineAgentTelemetryEvent branch in declaredKeysFor: agent_id is already copied unconditionally as identity plumbing before the declared-key loop, and the loop itself skips agent_id, so the branch had no runtime effect. Name the wire session id property key (WIRE_SESSION_ID_PROPERTY) so the session_id-to-sessionId mapping is explicit.

* refactor(agent-core-v2): flow ambient telemetry context to every event unconditionally

Remove the registry-key filtering and the FILTERED_CONTEXT_KEYS hard
filter from composeTelemetryProperties: the merged ambient now reaches
every event's properties, with session_id still remapped to the
camelCase sessionId key and explicit defined values winning on
collision. Explicit undefined values no longer clobber ambient fields.

With filtering gone, correctness for time-varying fields rests on
lifecycle discipline, so the loop now clears the ambient trace_id when
a step starts (mirroring the activeRequestTrace reset) instead of
relying on an explicit undefined payload value to mask the stale
mirror.

* refactor(agent-core-v2): move thinking_effort into the turn telemetry context

* refactor(agent-core-v2): replace the telemetry fragment registry with parent references
2026-09-02 20:50:23 +08:00
Kai
b6b9b374dd
feat(agent-core-v2): add a handoff step after forced stops and report subagent stop reasons (#3459)
* feat(agent-core-v2): add a handoff step after forced stops and report subagent stop reasons

- When the tool-call repeat breaker stops a turn, the loop now runs one
  text-only handoff step; tool calls issued in that step are refused and
  the turn ends with the same stop reason.
- Tool results can carry stopTurnReason; LoopRunResult and turn.ended
  expose the forced stop reason.
- Subagent results report stop_reason, a resume hint, and a next-step
  line; a turn that ends without a final message fails with
  agent.no_final_message, and the step-cap failure is rephrased for the
  parent model.
- Remove the subagent summary length policy and its continuation prompt.

* chore(agent-core-v2): regenerate the state manifest after merging main

* fix(agent-core-v2): run the handoff step at the step cap and surface swarm stop reasons

- The per-turn step cap no longer skips a queued handoff step, so a
  forced stop that lands on the last permitted step still produces the
  text handoff instead of a max_steps failure.
- AgentSwarm results carry the worker's stop reason and render it as a
  stop_reason attribute; a stuck worker now also triggers the resume hint.

* fix(agent-core-v2): keep the repeat-breaker classification and persist turn.ended stop reasons

- A handoff that ends without text keeps stop_reason repeat_breaker on
  the parent-facing failure instead of collapsing to no_final_message.
- Only a user cancellation maps to stop_reason cancelled; other kills
  report stopped and keep the resume hint.
- turn.ended persists stopReason in its durable record and the wire
  manifest lists it.
2026-09-02 17:32:25 +08:00
github-actions[bot]
0d45dddc57
ci: release packages (#3456)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-02 17:18:07 +08:00
Haozhe
cb11fc4bb1
fix(migration-legacy): stop re-prompting for kimi-cli migration once completed or dismissed (#3467) 2026-09-02 17:04:12 +08:00
7Sageer
ad5f0a5fa6
fix(agent-core-v2): re-remind uninjected AGENTS.md on directory access after context loss (#3462)
* fix(agent-core-v2): re-remind uninjected AGENTS.md on directory access after context loss

* fix(agent-core-v2): deduplicate AGENTS.md reminders across staggered same-step tool completions

* fix(agent-core-v2): inject AGENTS.md discovery reminders at step head from an access-fed queue

* Delete .changeset/agents-md-access-reminder.md

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

* fix(agent-core-v2): stop tracking read state for AGENTS.md reminders

* fix(agent-core-v2): suppress queued AGENTS.md reminders for same-step reads and deletions

---------

Signed-off-by: 7Sageer <sag77r@hotmail.com>
2026-09-02 16:52:07 +08:00
Grapedge
411572e166
feat(vscode): engine-backed @ file suggestions (#3453) 2026-09-02 14:16:20 +08:00
Kexin Liu
650d12f6c5
feat: add experimental turn-level file history snapshots (#3339)
* feat(agent-core-v2): add experimental turn-level file history snapshots

Back up the original content of every file the Edit/Write tools touch
(whole-file blob on first touch, captured through the tool executor's
will-execute hook so the read races nothing) and version all tracked
files at each main-agent turn boundary — a checkpoint at turn start and
one at turn end, so edits the user makes between turns attribute to no
turn. Unchanged files deduplicate by content hash; files past the 4 MiB
cap record an oversize sentinel fingerprinted by size and mtime; durable
checkpoint events are delta-encoded and fold back into replayable agent
state; reads (per-turn changes, checkpoint content) are computed from the
blobs on demand and serialize with writes. Gated behind
KIMI_CODE_EXPERIMENTAL_FILE_HISTORY (default off).

* feat(kap-server): serve turn-level file history over REST

GET /sessions/{session_id}/file-history/changes returns one turn's exact
per-file additions/deletions from the daemon's whole-file checkpoints;
/file-history/content returns a file's full content at either checkpoint
boundary. Persisted sessions resume on demand, matching the transcript
routes' cold-session behavior.

* fix(agent-core-v2): drain queued snapshots on agent teardown, single-sentence changeset

Register the snapshot queue with the unit ledger so agent-scope disposal
waits for an in-flight end checkpoint instead of racing runtime and log
teardown, and fold the changeset's enablement note into one sentence per
the changeset format rule.

* fix(agent-core-v2): bound aggregate LCS work per changes() call

Each file's line-count diff had its own 4M-cell LCS budget, so one
changes() request over a turn that rewrote hundreds of files could sum
to hundreds of millions of synchronous DP cells on the server event
loop (and on the snapshot queue). A per-call aggregate budget (16M
cells) is now threaded through diffChange/countLineDiff; files past the
budget fall back to the existing oversize no-counts marker. Files over
the per-file cap short-circuit without consuming aggregate budget.

* refactor(agent-core-v2): store per-turn checkpoint deltas instead of cumulative maps

Each checkpoint previously materialized the full session-wide entry
table, so changes() walked every file the session ever touched --
blob-reading and diffing files the turn never modified. Checkpoints now
keep only their own delta (entryAt already resolves by walking back);
when the cap evicts old checkpoints their entries fold into the new
head so resolution, maxVersion, and blob retention stay correct.
changes() derives its path set from the end checkpoint's delta, which
is exactly the files the turn touched.

* fix(agent-core-v2): gate live reads on the actually active turn

A start checkpoint without a matching end previously counted as live
whenever it was the latest checkpoint, so a session reloaded after a
crash or a lost end write compared that checkpoint against the current
workspace and attributed unrelated edits to the interrupted turn. The
service now tracks the active turn from TurnStarted/TurnEnded and takes
the live-disk path only while that turn is genuinely running; a cold
session reports no changes for an unpaired start instead.

* fix(agent-core-v2): reset file history in turn-sliced forks

A turn-indexed fork slices the journal at the next turn's first user
record, and the asynchronously written end checkpoint of the forked-at
turn can land after that boundary, leaving the fork with partial file
history. Instead of teaching the slicer to chase late records, the
slice now drops all file_history records: a turn-sliced fork starts
with an empty snapshot store and re-captures baselines on first touch,
while full forks copy the journal unchanged and keep complete history.

* fix(agent-core-v2): settle snapshots before fork copy, prune sliced-fork blobs

A fork accepted right after a turn completes could copy the blob
directory before the queued end checkpoint wrote its blobs, then copy a
journal that references them; fork() now awaits each live agent's file
history settling before copying. Turn-sliced forks drop file_history
records but previously kept every copied snapshot blob unreachable on
disk; pruneTruncatedForkFiles removes the file-history directory
alongside tasks and cron.

* fix(agent-core-v2): capture subagent edits into the main agent's file history

Non-main agents previously registered no tool hook, so a file first
touched by a delegated subagent had no baseline backup and never
appeared in the turn's changes. Subagent services now route their
file_io captures to the main agent's service, which records the
pre-image against its currently active turn; the existing end-of-turn
checkpoint then picks up the file's final state from disk.

* fix(agent-core-v2): hold loop quiescence on source agents while forking

The active-turn precheck and snapshot drain did not stop a prompt that
arrives mid-fork from starting a turn between the file copy and the
journal copy, letting the fork pick up journal records whose blobs were
written after the directory copy. fork() now acquires loop quiescence
on every live source agent (the undo/compaction idiom) and holds it
through both copy phases; prompts submitted meanwhile are held by the
loop and re-admitted on release.

* feat(agent-core-v2): retain file history for a five-turn sliding window

The 400-checkpoint cap with fold-on-eviction kept every touched file's
resolution (and its blobs, v1 forever) for the session's lifetime, so
disk and the per-boundary tracked-file scan both grew without bound.
Retention becomes a queue over the last five turns: checkpoints older
than the window are dropped outright, the tracked set shrinks to files
appearing in the remaining deltas, and their blobs -- v1 included --
are evicted. A file edited again after leaving the window re-captures
a fresh v1 baseline. Reads outside the window return empty and the
client already degrades to its local stats for those turns; the fold
machinery and the v1-forever rule are deleted.

* feat(agent-core-v2): capture a per-turn baseline so turns are self-contained

capture() previously fired only on a file's first touch in the session,
so a later turn's before-image resolved by walking back into older
turns' entries -- the cross-turn dependency that made window pruning
able to misreport an edge turn's modification as an addition. Every
turn now records its own baseline at first touch: when the pre-image
hash matches the latest known entry the entry is copied with its
existing blob key (no new content written), otherwise a new version is
backed up. changes()/contentAt() resolve within the turn's own start
checkpoint, and the prune-time fold remains only as the backstop for
files changed out-of-band mid-turn.

* refactor(agent-core-v2): turns record only their own tool snapshots, reads never walk back

Simplify the model to exactly what the feature displays: a turn records
the before-image of each file its tools touch (at first touch) and the
after-image of those same files at turn end, compared against the
turn's own baseline. changes() and contentAt() are direct lookups in
the turn's two checkpoints -- no cross-turn resolution, so the
prune-time fold and the walk-back helpers are deleted, the start
boundary scan is gone, and the live path iterates the turn's touched
files instead of every tracked file. An empty end record still lands on
turns without edits so the retention window keeps advancing.

Semantics change: files modified only by external means during a turn
(no tool touch) no longer appear in that turn's changes, and deletions
are recorded only for tool-touched files -- the turn diff now covers
exactly the tool activity, matching the client's row set.

* feat(kap-server): report file-history availability on the changes response

An empty changes list is ambiguous for clients: the flag may be off, or
the turn's checkpoint may have left the retention window. Carry the
service's enabled state so clients can tell the two apart.

* fix(agent-core-v2): retain the last five recorded turns, not five turn ids

Cancelled queued turns leave gaps in the ordinal sequence, so id
arithmetic evicted more history than the advertised window; retention
and blob eviction now keep the newest five distinct recorded turns. The
changeset sentence also catches up with the per-turn snapshot scope.

* fix(agent-core-v2): count only completed turns in the file-history window

A crash between a turn's first capture and its end checkpoint leaves a
start-only turn that used to occupy a retention slot and shrink the
usable window; retention and blob eviction now count turns with an end
record, dropping stale start-only leftovers while preserving anything
newer than the latest completed turn. The flag catalog description also
catches up with the per-turn snapshot scope.

* fix(agent-core-v2): flush the end checkpoint before evicting displaced blobs

dispatch queues the durable append without waiting for it, so a crash
between the window advancing and the journal flush could leave the old
checkpoints on disk with their blobs already deleted; the journal is now
flushed before any displaced blob is removed.

* fix(agent-core-v2): size snapshot reads to the statted file

Every snapshot read requested the 4 MiB limit, and the local fs backend
allocates the requested length up front — a turn touching many small
files paid hundreds of megabytes of zero-fill. Request the statted size
plus one byte instead; growth past the stat still surfaces as a length
mismatch, and a file already at the limit keeps the oversize path.

* fix(agent-core-v2): keep file-history blobs out of session exports, sweep crash orphans

Session export packed the whole session directory, shipping up to five
turns of whole-file snapshots inside the zip; the blob directory is now
excluded. A crash between the checkpoint flush and blob eviction could
also strand blobs no surviving checkpoint references — the first end
checkpoint of a session now sweeps unreferenced file-history blobs
once.

* feat(agent-core-v2): retain file history for the thirty most recently active sessions

Snapshots previously accumulated across every session a workspace ever
ran. A per-workspace LRU (persisted beside the sessions) is touched on
each end checkpoint; when it exceeds thirty sessions the least recently
active one's snapshot blobs are removed. An evicted session simply has
no snapshots — resuming it re-enters the window and rebuilds baselines
on the next edit, and a session evicted while idle self-heals because
blob writes recreate their directories.

* fix(agent-core-v2): keep the retention ledger out of the session listing

The per-workspace LRU document lived inside sessions/<workspace>, where
listSessionIds enumerates directory entries as session-id candidates;
it now lives in its own top-level file-history scope keyed by workspace
id.

* fix(agent-core-v2): review round — editing-turn window, full blob hashes, tests in-tree

Editless turns no longer emit end checkpoints, so pure chat neither
grows the wire journal nor evicts real edit history — the window now
keeps the last five editing turns. Blob keys use the full path hash
(truncation could collide and interleave histories), a lost blob
degrades its row to a countless marker instead of misreporting status,
and the window rule lives in one shared helper used by both the reducer
and blob eviction. The fork guard gets an honest message about
concurrent holds plus its own changeset, and the service/route/window
suites move into the tree with new unit coverage for the window helper
and diff budget.

* feat(agent-core-v2): report whether a turn's history is recorded

The changes response gains a recorded flag — true when the turn has a
start checkpoint and either its end checkpoint or a live turn — so
clients can tell an authoritative empty result from a turn whose
records were never made, lost to a crash, or displaced by retention.

* fix(agent-core-v2): recorded probes blob availability, content falls back for unchanged files

turnRecorded now verifies a keyed blob still exists, so a session whose
snapshots were displaced by the session window stops claiming authority
and clients keep their local rows. contentAt(end) resolves a file the
turn left unchanged from its start entry instead of returning nothing,
and session eviction deletes blobs before updating the ledger so a
crash retries the deletion instead of stranding it.

* fix(agent-core-v2): satisfy lint on the recorded probe

* fix(agent-core-v2): keep the retention ledger honest across eviction failure, fork and delete

A victim whose blob removal hits an IO error stays in the ledger for a
later retry instead of being delisted with its blobs stranded. A full
fork that copied snapshot blobs now enters the target session into the
ledger, so repeated forks cannot hold history outside the session
window, and deleting a session drops its ledger entry so ghost rows no
longer displace live sessions.

* chore(agent-core-v2): regenerate the wire manifest after the merge

* fix(agent-core-v2): count a trailing-newline-only change in authoritative stats

The daemon's line splitter adopts the client's last-line sentinel so a
file differing only in its trailing newline reports 1/1 instead of 0/0,
keeping authoritative counts in agreement with the client. Closes the
follow-up tracked in #3449.

---------

Co-authored-by: user <user@userdeMacBook-Pro.local>
2026-09-02 14:04:56 +08:00
github-actions[bot]
e27ee60894
ci: release packages (#3347)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-02 13:57:06 +08:00
Haozhe
a23ff56358
feat(kap-server): add POST /workspaces/{id}/add-dir endpoint (#3451) 2026-09-02 12:47:15 +08:00
qer
0f39b2cf3a
fix(kap-server): report the real event watermark as last_seq in getSession (#3436)
* fix(kap-server): report the real event watermark as last_seq in getSession

GET /api/v1/sessions/{id} hardcoded last_seq to 0, so event subscribers
catching up from the fetched watermark always replayed the whole session
journal from seq 0. Historical work_changed frames then surfaced as
spurious busy state in clients. Return the broadcaster's journal cursor
(live seq, or the persisted watermark for cold sessions) so subscribers
land on the journal tail with an empty replay.

* fix(kap-server): capture the event cursor before session state in getSession

A profile update landing between the summary read and the cursor read
could produce a response pairing stale fields with a cursor that already
covers the update event; subscribers from that last_seq would then skip
the event entirely. Capture the cursor first so every state read is at
least as new as the watermark; later events still replay past it.

The watermark test now relies on the dispatch queue ordering behind
getCursor instead of wall-clock polling.
2026-09-02 11:57:26 +08:00
Haozhe
04461960e9
fix(migration-legacy): faithfully migrate kimi-cli user data into kimi-code (#3446)
* fix(migration-legacy): faithfully migrate kimi-cli user data into kimi-code

* fix(migration-legacy): faithfully migrate kimi-cli user data into kimi-code
2026-09-02 11:32:23 +08:00
Haozhe
b4ae7f875d
fix(agent-core-v2): allow Bash cwd outside the workspace roots (#3444)
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
Release / Publish native release assets (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
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
Publish VS Code extension / Publish VSIX to marketplaces (push) Waiting to run
- drop the built-in escape assertion from RuntimeWorkspaceView.resolve so it is a pure path mapping
- return the validated path from assertAllowed and compose it explicitly in terminalService
- add a bash test covering cwd outside the workspace roots
2026-09-02 09:04:25 +08:00
Haozhe
ae7a6dc6fb
refactor(acp): remove the legacy acp-adapter package (#3434) 2026-09-01 23:59:20 +08:00
Haozhe
ab565e0816
docs(transcript): rewrite SDK document against the current contract (#3437)
* docs(transcript): add SDK contract document

* docs(transcript): rewrite SDK document against the current contract
2026-09-01 23:03:04 +08:00
Haozhe
deed1e935c
docs(transcript): add SDK contract document (#3432) 2026-09-01 22:27:49 +08:00
Haozhe
742e1197a9
feat(agent-core-v2): persist step retry and interrupt events to the wire (#3428)
* feat(agent-core-v2): persist step retry and interrupt events to the wire

* feat(transcript): create the missing interrupted step in the cold fold
2026-09-01 21:56:28 +08:00
Haozhe
ceb51535ef
feat(cli): add the kimi session list subcommand (#3425)
* feat(cli): add the kimi session list subcommand

- add the session command group with list: cwd scope by default, --all/--cwd/--archived/--limit/--json
- pass includeArchived through the SDK listSessions options (v2 klient query, v1 includeArchive mapping)

* docs: condense the session list changeset to one sentence

* fix(cli): sanitize session list rows and tidy option types

- strip control characters and line breaks from user-controlled row fields
- declare cwd/limit as plain optional properties without undefined unions
2026-09-01 21:41:52 +08:00
Haozhe
442b56391b
fix(agent-core-v2): let experimental config override the master flag env (#3427) 2026-09-01 21:36:57 +08:00
Haozhe
33eee42601
fix(agent-core-v2): reproject a stale session index at startup (#3422)
- add mtime to the file system storage service (node-fs stat, memory write clock)
- record the source max mtime in the session index checkpoint at projection
- compare the cheap mtime signal before adopting a persisted manifest on prepare
- refresh the checkpoint mtime after reconcile so warm starts stay scan-free
2026-09-01 21:20:00 +08:00
Haozhe
9c37feb473
perf(agent-core-v2): fork sessions without materializing the target (#3421)
* fix(agent-core-v2): persist plan.revision as agent-relative key

- replace the session-scoped `path` field in durable plan.revision records
  with an agent-relative `key`, resolved to a display path at read and
  projection time against the current agent/session scope
- migrate legacy `path` records during wire restore and rewrite the journal
  once migration succeeds, emitting low-cardinality
  `wire_plan_revision_migrated` telemetry
- tolerate journal truncation during the migration rebuild and keep the
  legacy `path` display in cold transcript folds for unmigrated records
- keep external transcript marker `path` and meta `reviewPath` projections
  unchanged

* perf(agent-core-v2): fork sessions without materializing the target

- copy session files byte-for-byte (wire.jsonl included, parallel file
  writes) and append the forked marker per agent instead of parsing and
  rewriting every wire journal
- write the forked session's state.json, agent registry, and session
  index entry directly without creating a live session or agent scopes;
  fork returns SessionMeta and SessionForkedEvent drops the scope handle
- keep turnIndex truncation on the per-record path
- kap-server fork/createChild routes, the klient facade and wire
  contract, and the node-sdk forkSession resume the forked session
  through the normal resume path when a live handle is needed
- stop healing truncated source wires during fork; the forked session
  repairs its own copy lazily on resume
- add the `kimi fork [--cwd] [-y]` CLI command
2026-09-01 19:46:35 +08:00
Grapedge
76c1a7a347
refactor(agent-core-v2): simplify the default system prompt (#3390)
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
Publish VS Code extension / Publish VSIX to marketplaces (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
2026-09-01 18:16:59 +08:00
tpoisonooo
c3bf6f9d2d
feat(agent-core-v2): rework tower mode entry and surface worker deaths (#3399)
Tower mode is now entered only manually — /tower on, or /tower
<base-branch> to also pin the local branch missions merge back into. The
agent can no longer enter it on its own: TowerInit refuses while the mode
is off and points at the slash command.

/tower <base-branch> is deterministic end to end: a missing base branch is
created from the current checkout (uncommitted changes committed onto it
as a labeled WIP snapshot), the checkout switches to it, and the tower
workspace is initialized immediately instead of relying on the model to
apply the base. With an existing workspace the tower rebases onto the
requested base when no missions are open and refuses naming the blocking
missions otherwise. The base rides the tower_mode.enter event into the new
tower.base state key and TowerInit falls back to it.

Tower agent deaths (failed/timed_out/killed/lost) are recorded in the
tower protocol: TowerStatus marks dead roster entries and warns about
missions whose owner died, with a resume hint. The tower console prompt
now requires a per-worker deliverables summary before TowerTeardown.

The session profile REST surface accepts tower_base so web clients can
turn tower mode on with /tower <base-branch> instead of sending the
argument as a prompt.

Co-authored-by: konghuanjun <konghuanjun@moonshot.ai>
2026-09-01 18:03:13 +08:00
7Sageer
4d7f32e1aa
fix(agent-core-v2): drop compaction mechanics from the AGENTS.md discovery reminder (#3420)
* fix(agent-core-v2): drop compaction mechanics from the AGENTS.md discovery reminder

The re-injection trigger is harness mechanics the model cannot act on, and the unread-path condition never fires from the model's perspective. End the reminder at the actionable instruction.

* fix(agent-core-v2): reword the AGENTS.md discovery reminder lead

Lead with the files instead of the paths, and replace harness vocabulary (touched / covered by / injected instructions) with terms the model can place: apply to, your system prompt.
2026-09-01 17:22:05 +08:00
7Sageer
379241e008
feat(agent-core-v2): report enabled experimental flags in session_started telemetry (#3419)
* feat(agent-core-v2): report enabled experimental flags in session_started telemetry

Add a sorted, comma-separated experimental_flags property to the v2
session_started event so feature-gated metrics gain a session-granular
exposure denominator, and carry the post-apply enabled set on the TUI
experimental_features_apply event to bound mid-session flag flips.

* feat(node-sdk): carry experimental flags on the harness session_started row

The v2 in-process path emits session_started twice (engine-side from
SessionLifecycleService, harness-side from KimiHarness), and only the
engine row carried experimental_flags, so consumers could double-count
or miss the flag dimension. Merge a per-emission dynamic getter into the
harness row, wired to the in-process engine's flag service, so both
rows report the same enabled flag set.

* fix(node-sdk): keep experimental_flags canonical on session_started

A caller-supplied experimental_flags in per-call sessionStartedProperties
could overwrite the engine-owned dynamic value, breaking row-to-row flag
consistency. Merge the dynamic properties after the session-scoped ones
so engine-owned keys always win.

* fix(agent-core-v2): count tower as exposure only once assembled

The tower flag reacts live to mid-process flips, but TowerFeature's
tools and profiles are assembled at App scope construction, so a session
started after an in-process flip cannot actually use tower. Filter it
out of experimental_flags on both session_started producers unless
isTowerFeatureAssembled says the feature is assembled in this process,
keeping the exposure denominator honest.

* test: recalibrate fixtures for the added constructor param and drop timing-sensitive tower assertion

The WorkspaceInstanceManager test builds the service with positional
args; the new flags param shifted unitHostFactory one slot. The tower
inclusion assertion in the SDK integration test depended on feature
assembly winning the race against async config load, which slow CI
runners lose; tower assembled-state coverage stays with the tower
service tests.

* refactor(agent-core-v2): move flag exposure gating into the flag definition

Telemetry consumers hardcoded tower's assemble-at-startup semantics to
keep it out of experimental_flags until assembled. Push the gate into
FlagDefinitionInput as an optional isExposed predicate owned by the
flag's own domain, expose it as IFlagService.exposedIds(), and let both
session_started producers call it — no feature-specific knowledge leaks
into the SDK or the session lifecycle.
2026-09-01 17:14:35 +08:00
7Sageer
0b8808a2cd
fix(agent-core-v2): re-remind subdirectory AGENTS.md after context compaction (#3409)
* fix(agent-core-v2): re-remind subdirectory AGENTS.md after context compaction

Deliver the discovery reminder through the reminder runtime's register()
channel so it re-injects whenever the previous reminder leaves the context
(compaction, /clear, or undo), instead of firing a one-shot notify() that
compaction silently drops while the known-set survives.

Discovery bookkeeping splits into agentsMdReminder.pending (discovered, not
yet read) and agentsMdReminder.known (injected or read); the provider injects
only pending paths not covered by the last injection's disclosure. A newly
created AGENTS.md lands in pending until read; a modified one counts as
injected.

* fix(agent-core-v2): drop deleted AGENTS.md from reminder bookkeeping

A discovered-but-unread AGENTS.md that gets deleted stayed in
agentsMdReminder.pending, so the next re-injection after context loss
pointed the model at a file that no longer exists. Remove deleted paths
from both the pending and known sets on the watcher event.

* Delete .changeset/agents-md-reminder-compaction-reset.md

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

---------

Signed-off-by: 7Sageer <sag77r@hotmail.com>
2026-09-01 17:06:55 +08:00
Kexin Liu
a26fca784d
test: catch fixtures up with the model-validation removal (#3418)
#3411 dropped two positional constructor params from
WorkspaceInstanceManager, shifting the agent-profile stub the
Reflect.construct fixture pins by index, and turned the broken
subagent-pool session create from VALIDATION_FAILED into a success;
both suites fail on main since then.

Co-authored-by: user <user@userdeMacBook-Pro.local>
2026-09-01 15:53:22 +08:00
Kimi Agent
82bf0a8dd2
fix(agent-core-v2): parse git status porcelain with -z for non-ASCII paths (#3415)
git status --porcelain=v1 without -z C-quotes non-ASCII paths under
git's default core.quotePath, and parsePorcelain consumed the quoted
form verbatim while the posix() helper turned each \3xx octal escape
into a fake path segment — the changes tree then split those segments
on '/' and rendered Chinese filenames as bogus directory chains, and
diff requests for such entries failed the same way.

Run porcelain with -z (NUL-separated, never quoted; rename records are
XY new\0old with the new path first) and drop the posix() helper —
porcelain already emits '/' separators on every platform. The v1 engine
shares the bug and is intentionally left unchanged for now.

Refs #3414

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
Co-authored-by: liruifengv <liruifeng1024@gmail.com>
2026-09-01 15:06:39 +08:00
7Sageer
7bc5b2027c
refactor(agent-core-v2): deliver the subagent fork notice via reminder injection (#3412) 2026-09-01 14:02:01 +08:00
Haozhe
5e57618fc8
fix(agent-core-v2): allow sessions without valid models (#3411)
* fix(agent-core-v2): allow sessions without valid models

* fix(agent-core-v2): wait for model initialization

* fix(agent-core-v2): align session lifecycle dependencies
2026-09-01 12:38:55 +08:00
Haozhe
15bf58555b
refactor(agent-core-v2): replace agent runtime with agent-scoped DI services (#3402)
* refactor(agent-core-v2): migrate todo domain to agent-scoped DI service

* refactor(agent-core-v2): migrate skill domain to agent-scoped DI service

* refactor(agent-core-v2): migrate reminder domain to agent-scoped DI service

* refactor(agent-core-v2): migrate interaction domain to agent-scoped DI service

* refactor(agent-core-v2): migrate cron domain to agent-scoped DI service

* refactor(agent-core-v2): migrate dateChange domain to agent-scoped DI service

* refactor(agent-core-v2): migrate goal domain to agent-scoped DI service

* refactor(agent-core-v2): remove agent runtime infrastructure

* docs(agent-core-v2): rewrite agent domain standard as agent-scoped DI service

* fix(agent-core-v2): restore actor services on late feature re-provide and order agent-created events after metadata registration
2026-08-31 22:53:29 +08:00