Skip to content

fix(webchat): suppress partial NO_REPLY tokens during streaming#32052

Closed
ningding97 wants to merge 1 commit intoopenclaw:mainfrom
ningding97:fix/32015-webchat-no-reply-leak
Closed

fix(webchat): suppress partial NO_REPLY tokens during streaming#32052
ningding97 wants to merge 1 commit intoopenclaw:mainfrom
ningding97:fix/32015-webchat-no-reply-leak

Conversation

@ningding97
Copy link

Closes #32015

Problem

During streaming in webchat, the delta handler only checks for the full NO_REPLY token via isSilentReplyText. When tokens arrive incrementally (e.g. "NO""NO_R""NO_REPLY"), the partial text passes the check and gets rendered as a visible "NO" bubble.

Fix

Add isSilentReplyPrefixText check in emitChatDelta to suppress partial silent token prefixes during streaming. The existing isSilentReplyPrefixText function already handles this exact case (checks if text looks like a prefix of the silent token).

Tests

pnpm test -- src/gateway/server-chat (15 tests pass)

During streaming, the webchat delta handler only checked for the full
NO_REPLY token. Partial tokens like "NO" or "NO_RE" were sent to the
UI before the complete token arrived, causing a visible "NO" bubble.

Add isSilentReplyPrefixText check to suppress partial silent tokens
in the streaming delta path.

Closes openclaw#32015
Copy link

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

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: 14de324e2d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

return;
}
// Suppress partial NO_REPLY tokens during streaming (e.g. "NO" before full "NO_REPLY" arrives)
if (isSilentReplyPrefixText(cleaned, SILENT_REPLY_TOKEN)) {

Choose a reason for hiding this comment

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

P2 Badge Suppress pre-underscore silent token chunks

The new isSilentReplyPrefixText gate does not catch the first streamed chunks like "N"/"NO", because that helper only returns true once an underscore is present (it explicitly rejects these cases in src/auto-reply/tokens.ts and src/auto-reply/tokens.test.ts). In streams that tokenize as "NO" then "NO_REPLY", this still emits a visible NO delta before suppression, so the partial-token leak this commit targets remains reproducible.

Useful? React with 👍 / 👎.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 2, 2026

Greptile Summary

This PR adds a check for partial NO_REPLY tokens during streaming to prevent them from being displayed to users. The fix adds isSilentReplyPrefixText validation in the emitChatDelta function, which suppresses partial tokens like "NO_", "NO_R", "NO_RE", etc. that arrive before the complete "NO_REPLY" token.

Key changes:

  • Added import for isSilentReplyPrefixText from the tokens module
  • Added prefix check after the existing full token check (lines 298-301)
  • The check prevents partial silent token prefixes from being emitted as chat deltas during streaming

Implementation correctness:

  • The fix follows the same pattern already used in typing.ts, agent-runner-execution.ts, and streaming-directives.ts
  • The order of checks is correct: full token check first, then prefix check
  • The isSilentReplyPrefixText function is well-tested and requires an underscore to avoid false positives with natural language (e.g., "NO" or "No" won't be suppressed)

Testing:

  • All 15 existing tests pass
  • The isSilentReplyPrefixText function has comprehensive test coverage in tokens.test.ts

Confidence Score: 5/5

  • This PR is safe to merge with no identified risks
  • The change is minimal (4 lines), well-scoped, and follows an established pattern used consistently across the codebase. The function being used is already tested and proven in production use elsewhere. No logical errors, security issues, or breaking changes identified.
  • No files require special attention

Last reviewed commit: 14de324

@Takhoffman
Copy link
Contributor

Closing as superseded by merged #32183 and already-landed streaming lead-fragment fix #32116 for the NO_REPLY leak family.

@Takhoffman Takhoffman closed this Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Webchat renders NO_REPLY as visible “NO” (silent token leak)

2 participants