Skip to content

fix(acp): stream engine-triggered follow-up turns - #2769

Open
haveanicedavid wants to merge 1 commit into
MoonshotAI:mainfrom
haveanicedavid:fix/acp-background-turn-updates
Open

fix(acp): stream engine-triggered follow-up turns#2769
haveanicedavid wants to merge 1 commit into
MoonshotAI:mainfrom
haveanicedavid:fix/acp-background-turn-updates

Conversation

@haveanicedavid

Copy link
Copy Markdown

Related Issue

No related issue.

Problem

When Kimi starts a detached background task, the client-initiated session/prompt finishes after Kimi reports that the task started. When the task later completes, the engine starts another turn for the main agent.

The TUI displays that follow-up turn, but ACP clients receive nothing. The messages are persisted in the Kimi session but missing from the live ACP stream.

AcpSession discarded assistant, thinking, tool, and turn-end events unless their turn ID matched an active TurnDriver. Because engine-triggered follow-up turns have no client prompt driver, their events were silently dropped.

What changed

  • Forward events from the subscribed main-agent stream even when no client prompt driver exists.
  • Allow only the matching turn.ended event to settle an active session/prompt.
  • Preserve buffered events across successful, blocked, and rejected prompt launches.
  • Add regression coverage for follow-up delivery, event ordering, settlement isolation, and no-launch handling.
  • Add a patch changeset for the bundled CLI fix.

This separates prompt-request settlement from delivery of the session’s agent event stream.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem 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.

@changeset-bot

changeset-bot Bot commented Aug 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c3660a1

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c3660a186a

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 906 to +907
const driver = this.driverFor(event.turnId);
if (driver === undefined) return;
const error = event.error as { readonly code: string; readonly message?: string } | undefined;
this.settleDriver(driver, () => {
// Auth failures must surface as a JSON-RPC `auth_required` error
// so the client triggers its re-auth flow, not a silent `end_turn`.
if (event.reason === 'failed' && isAuthError(error)) {
driver.reject(RequestError.authRequired(undefined, error?.message));
return;
}
driver.resolve({ stopReason: turnEndReasonToStopReason(event.reason, error) });
});
if (driver !== undefined) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Track driverless turns for cancellation

When a background completion starts a long engine-triggered follow-up after the originating session/prompt has settled, driverFor is undefined here and the turn is intentionally allowed to keep streaming, but its turn ID is never retained. Consequently, cancel() returns immediately whenever this.driver is undefined, so a subsequent ACP session/cancel cannot stop the visible model or tool execution. Track active engine turns via turn.started/turn.ended, or otherwise issue an unaddressed cancel when a driverless turn is active.

Useful? React with 👍 / 👎.

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