Skip to content

fix(agent-core-v2): let steer interrupt background task waits - #3697

Merged
RealKai42 merged 1 commit into
mainfrom
fix/wait-for-steer
Sep 10, 2026
Merged

RealKai42 merged 1 commit into
mainfrom
fix/wait-for-steer

Conversation

@RealKai42

Copy link
Copy Markdown
Collaborator

Related Issue

No linked GitHub issue. This addresses new steering messages being blocked while the agent waits for a background task.

Problem

When the model calls WaitFor, steering adds input for the next step but does not release the active wait. A user can therefore wait up to 600 seconds before the model handles their new message, even though the background task runs independently.

What changed

  • Pass a separate steer signal through tool execution. WaitFor returns a non-error interrupted result when steered, preserving tool history and leaving background tasks running.
  • Keep the signal active until the steered input is consumed. This covers input arriving before execution, consecutive steering messages, and multiple waits in one batch; subsequent waits work normally after the input is consumed.
  • Preserve cancellation semantics and completion-notification deduplication. Other foreground tools in the same batch still finish before the next model request.
  • Add seven regression cases, update the English and Chinese interaction/tool documentation, and include a CLI patch changeset.

Validation:

  • 442 tests passed across the task, loop, tool-executor, prompt, and underlying agent/turn state-machine suites.
  • pnpm --filter @moonshot-ai/agent-core-v2 run typecheck passed.
  • pnpm run lint passed with zero errors; existing repository warnings remain.
  • pnpm -C docs run build passed.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue (no linked issue; the problem is described above).
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 10, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-10T07:08:39.838897Z f0a9c84 PR opened
🔒 Security Review ✅ Completed 2026-09-10T07:13:09.373454Z f0a9c84 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@changeset-bot

changeset-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f0a9c84

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Sep 10, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@f0a9c84
npx https://pkg.pr.new/@moonshot-ai/kimi-code@f0a9c84

commit: f0a9c84

@RealKai42
RealKai42 merged commit 5e452fc into main Sep 10, 2026
16 checks passed
@RealKai42
RealKai42 deleted the fix/wait-for-steer branch September 10, 2026 09:13
@github-actions github-actions Bot mentioned this pull request Sep 10, 2026
teknium1 added a commit to NousResearch/hermes-agent that referenced this pull request Sep 13, 2026
…ort of MoonshotAI/kimi-code#3697)

A user message sent mid-turn (CLI busy_input_mode=interrupt, gateway priority
redirect, ACP redirect) goes through AIAgent.redirect(), which during tool
execution degrades to steer() + request_yield() on the tool worker threads.
The local terminal backend's foreground wait honours the yield (adopting the
process into the background registry), but ProcessRegistry.wait() — the
process_manage(action='wait') path — never checked it: a model sitting in a
wait on an already-background process parked the user's message for up to the
full wait window (default 180s, clamp allows more).

wait() now consumes a pending yield on its own thread each poll pass and
returns status "interrupted" with process_running=true and a note telling the
model to respond to the user; the process is untouched and still
notify-tracked. The plain-interrupt and timeout paths are unchanged.

Live repro: on origin/main, request_yield() against a thread blocked in
wait(timeout=12) had no effect (wait ran to timeout); after this change the
wait releases in <1s with status=interrupted, process still running.

Port of MoonshotAI/kimi-code#3697 ("let steer interrupt background task
waits") adapted to Hermes' per-thread yield mechanism from 4632923.
teknium1 added a commit to NousResearch/hermes-agent that referenced this pull request Sep 13, 2026
…ort of MoonshotAI/kimi-code#3697)

A user message sent mid-turn (CLI busy_input_mode=interrupt, gateway priority
redirect, ACP redirect) goes through AIAgent.redirect(), which during tool
execution degrades to steer() + request_yield() on the tool worker threads.
The local terminal backend's foreground wait honours the yield (adopting the
process into the background registry), but ProcessRegistry.wait() — the
process_manage(action='wait') path — never checked it: a model sitting in a
wait on an already-background process parked the user's message for up to the
full wait window (default 180s, clamp allows more).

wait() now consumes a pending yield on its own thread each poll pass and
returns status "interrupted" with process_running=true and a note telling the
model to respond to the user; the process is untouched and still
notify-tracked. The plain-interrupt and timeout paths are unchanged.

Live repro: on origin/main, request_yield() against a thread blocked in
wait(timeout=12) had no effect (wait ran to timeout); after this change the
wait releases in <1s with status=interrupted, process still running.

Port of MoonshotAI/kimi-code#3697 ("let steer interrupt background task
waits") adapted to Hermes' per-thread yield mechanism from 4632923.
teknium1 added a commit to NousResearch/hermes-agent that referenced this pull request Sep 13, 2026
…ort of MoonshotAI/kimi-code#3697)

A user message sent mid-turn (CLI busy_input_mode=interrupt, gateway priority
redirect, ACP redirect) goes through AIAgent.redirect(), which during tool
execution degrades to steer() + request_yield() on the tool worker threads.
The local terminal backend's foreground wait honours the yield (adopting the
process into the background registry), but ProcessRegistry.wait() — the
process_manage(action='wait') path — never checked it: a model sitting in a
wait on an already-background process parked the user's message for up to the
full wait window (default 180s, clamp allows more).

wait() now consumes a pending yield on its own thread each poll pass and
returns status "interrupted" with process_running=true and a note telling the
model to respond to the user; the process is untouched and still
notify-tracked. The plain-interrupt and timeout paths are unchanged.

Live repro: on origin/main, request_yield() against a thread blocked in
wait(timeout=12) had no effect (wait ran to timeout); after this change the
wait releases in <1s with status=interrupted, process still running.

Port of MoonshotAI/kimi-code#3697 ("let steer interrupt background task
waits") adapted to Hermes' per-thread yield mechanism from 4632923.
loteiron pushed a commit to loteiron/ZeusAgent that referenced this pull request Sep 14, 2026
…ort of MoonshotAI/kimi-code#3697)

A user message sent mid-turn (CLI busy_input_mode=interrupt, gateway priority
redirect, ACP redirect) goes through AIAgent.redirect(), which during tool
execution degrades to steer() + request_yield() on the tool worker threads.
The local terminal backend's foreground wait honours the yield (adopting the
process into the background registry), but ProcessRegistry.wait() — the
process_manage(action='wait') path — never checked it: a model sitting in a
wait on an already-background process parked the user's message for up to the
full wait window (default 180s, clamp allows more).

wait() now consumes a pending yield on its own thread each poll pass and
returns status "interrupted" with process_running=true and a note telling the
model to respond to the user; the process is untouched and still
notify-tracked. The plain-interrupt and timeout paths are unchanged.

Live repro: on origin/main, request_yield() against a thread blocked in
wait(timeout=12) had no effect (wait ran to timeout); after this change the
wait releases in <1s with status=interrupted, process still running.

Port of MoonshotAI/kimi-code#3697 ("let steer interrupt background task
waits") adapted to Hermes' per-thread yield mechanism from 463292351fe.

Adapted for ZeusAgent with local regression coverage.
Upstream-Commit: cbd4492f1fc3b336619a7871b5dae94b86975693
7723qqq added a commit to 7723qqq/kimi-code that referenced this pull request Sep 17, 2026
Brings the fork's Rust engine up to the behaviors ported from upstream since
0.42.0, and moves the version to 2.0.0 to follow upstream (never bumped
independently).

Ports landed here, each recorded in packages/kimi-agent/ROADMAP.md §6.2 and
scripts/upstream-v2-delta-allowlist.json with its own evidence:

- MoonshotAI#3688 MCP media originals are preserved instead of flattened to a text
  preview: src/mcp/output.rs adds the content-block conversion and the
  result-to-delivery path, FileStore gains content-addressed writing, and the
  attachment reference is resolvable by Read/ReadMediaFile.
- MoonshotAI#3734 streamed attempt state is invalidated when the LLM requester retries:
  a turn-scoped tool-call id ledger, streamed tool-call deltas from all three
  wire protocols, and an attempt guard that rolls back on every failure exit.
- MoonshotAI#3697 steer interrupts a background-task wait — plus the blocking wait it
  needed. The engine's WaitFor had been routed through a synchronous local
  store, so a 5s wait returned in 6ms reporting a timeout; the toolset now
  waits on its own task runner, and a steer signal ends that wait early
  without cancelling the turn or its tasks. WaitFor gains the wait-any form.
- MoonshotAI#3846 an MCP tool call returning 401 flips the server to needs-auth.
- MCP servers connect once per process, starting at startup.
- AI session titles are generated through the managed chat_title tool.
- The abort fix in the preceding commit.

Also refreshes the ROADMAP evidence blocks, the upstream delta allowlist, the
bilingual docs those behaviors surface in, and the TUI rendering for the new
wait status.
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.

1 participant