Skip to content

chore: sync upstream/main 19 commits (2026-09-05) - #57

Merged
arrrrny merged 20 commits into
masterfrom
sync/fork-sync-resolution-2026-09-05
Sep 5, 2026
Merged

chore: sync upstream/main 19 commits (2026-09-05)#57
arrrrny merged 20 commits into
masterfrom
sync/fork-sync-resolution-2026-09-05

Conversation

@arrrrny

@arrrrny arrrrny commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Resolves #56

sailist and others added 20 commits September 3, 2026 14:32
…cts (MoonshotAI#3504)

* test: speed up kap-server suite and exclude minidb from default projects

* test(kap-server): restore baseline server after sessions tests replace it
…try in v2 print mode (MoonshotAI#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
… scanning (MoonshotAI#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.
…otAI#3485)

* docs(zh): restyle configuration and customization sections

Editorial pass across 11 pages: clear explanatory dashes, replace arrow
cross-references with inline links, compress oversized table cells while
keeping operational facts (value ranges, override precedence, activation
conditions), split >5-sentence paragraphs by theme, fold interface
contracts and low-frequency internals into details blocks, add map
sentences to multi-paragraph sections, add subcommand overview table to
kimi-command reference. Add /provider manager screenshot to media.

* docs(zh): restore dangerous_command_guard, fix trust prompt default and secondary-model default

- config-files: restore the dangerous_command_guard paragraph dropped
  during the style pass (regression, content from upstream MoonshotAI#3290)
- mcp: the trust prompt defaults to Trust this folder per
  trust-prompt.test.ts; docs had the direction reversed (pre-existing)
- config-files: subagent model pool defaults on since MoonshotAI#3334;
  KIMI_CODE_EXPERIMENTAL_SECONDARY_MODEL=0 disables (pre-existing staleness)

* docs(zh,en): sync en mirrors and fix anchor slugs

Add restyled en mirrors for all 11 configuration/customization pages,
mirroring the zh structure (section parity, map sentences, compressed
cells, details folds) while keeping en phrasing.

Fix anchor slugs in both locales (underscore kept, dots dropped per
@mdit-vue slugify): loop_control, openai_responses, kimi_model_,
systemmd variants; retarget renamed permission-mode section
(yolo/auto -> The three permission modes / 三种权限模式).
…oonshotAI#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
* 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.
… compaction notes at the wire journal (MoonshotAI#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
…nshotAI#3521)

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
Co-authored-by: qer <wbxl2000@outlook.com>
…inline their answers (MoonshotAI#3522)

* 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.
…ion mode (MoonshotAI#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
…history (MoonshotAI#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.
…3515)

- rename the mode commands to /yolo and /auto (formerly
  /ask-when-needed and /never-ask) and drop their on/off arguments
- running either command now opens the permission mode list with the
  corresponding mode preselected; Enter confirms the switch
- decouple the choice picker's initial cursor from the current-value
  marker via a new initialValue option
- after a mode switch, show the mode-specific description as the yellow
  status line instead of the generic unconfirmed-changes warning
…I#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
code-app: 054a6e98b9c992ee4fe5f83c0091b7e931561aba

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…otAI#3551)

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
* fix(vis): align with current agent-core-v2

* fix(vis): harden partial session recovery

* fix(vis): harden file history rendering

* fix(vis): validate persisted debug payloads
Resolved 7 merge conflicts:
- apps/kimi-code/src/tui/commands/config.ts: Keep both disableFeedbackSurvey and favoriteModels
- apps/kimi-code/src/tui/config.ts: Keep both disableFeedbackSurvey and favoriteModels
- apps/kimi-code/test/tui/commands/update-preferences.test.ts: Keep both fields
- apps/kimi-code/test/tui/config.test.ts: Keep both fields
- packages/agent-core-v2/src/agent/fullCompaction/compactionOps.ts: Accept upstream wireRanges
- packages/agent-core-v2/src/agent/fullCompaction/fullCompactionService.ts: Keep fork secondary cascade + upstream wire service
- packages/agent-core-v2/src/app/telemetry/events.ts: Keep both upstream context budget events and fork model tracking

All fork-owned features preserved:
- favoriteModels (model favorites)
- compaction-model secondary cascade
- model/model_display telemetry fields

All upstream improvements accepted:
- disableFeedbackSurvey (session rating survey)
- fullCompactionWireRangesKey
- context budget reminder events
- ahead reminder telemetry

Closes #56
@arrrrny
arrrrny merged commit 032a449 into master Sep 5, 2026
9 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sync: upstream merge conflicts require manual resolution

8 participants