Skip to content

fix(discord): keep clarify prompts visible when embeds are hidden - #36186

Closed
carltonawong wants to merge 1 commit into
NousResearch:mainfrom
carltonawong:fix/discord-clarify-visible-content
Closed

fix(discord): keep clarify prompts visible when embeds are hidden#36186
carltonawong wants to merge 1 commit into
NousResearch:mainfrom
carltonawong:fix/discord-clarify-visible-content

Conversation

@carltonawong

Copy link
Copy Markdown
Contributor

Summary

Discord web/mobile can render the component buttons for an embed-backed prompt while hiding the embed body itself. That leaves send_clarify() prompts in a dangerous state: the user can see the choices, but not the question/draft text they are choosing about.

This adds a narrow defensive fallback for Discord send_clarify() only: the critical prompt body is also sent as normal message.content, while preserving the existing embed and button view.

Related: #33681

Changes

  • plugins/platforms/discord/adapter.py
    • adds visible normal-message content for Discord clarify prompts
    • keeps the existing embed + button UX intact
    • truncates the visible fallback at Discord's 2000-character content limit with an explicit warning not to approve unless the full prompt/draft is visible elsewhere
  • tests/gateway/test_discord_clarify_buttons.py
    • updates the clarify send regression to assert the prompt/draft text is present in normal message content alongside the embed and view

Scope

This intentionally covers only send_clarify().

Issue #33681 notes the same Discord embed+components rendering class may affect send_exec_approval, send_slash_confirm, send_update_prompt, the model picker, and free-response cards. Those are left for a follow-up so this PR stays small and reviewable.

The reason to start with clarify is that clarify prompts can contain draft/approval text where choosing a button without seeing the body is unsafe.

Validation

  • python -m pytest -o addopts='' tests/gateway/test_discord_clarify_buttons.py -q14 passed
  • python -m py_compile plugins/platforms/discord/adapter.py tests/gateway/test_discord_clarify_buttons.py
  • git diff --check
  • Live Discord smoke test on a running gateway: clarify buttons rendered and the prompt/draft body was visible in normal message content above the buttons.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/discord Discord bot adapter labels Jun 1, 2026

@mxnstrexgl mxnstrexgl 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.

LGTM — automated review passed. No security, quality, or test coverage issues detected.

@carltonawong
carltonawong force-pushed the fix/discord-clarify-visible-content branch from c8bc3d5 to 6dcb9b2 Compare June 1, 2026 02:42
@carltonawong

Copy link
Copy Markdown
Contributor Author

Refreshed this branch on top of current main.

The PR is still intentionally narrow: it only changes the Discord send_clarify() send path, preserving the existing embed + button UX while adding normal message.content as a defensive visibility fallback for the critical prompt/draft body.

Validated after rebasing:

python -m pytest -o addopts='' tests/gateway/test_discord_clarify_buttons.py -q
python -m py_compile plugins/platforms/discord/adapter.py tests/gateway/test_discord_clarify_buttons.py
git diff --check origin/main...HEAD

Results:

  • 14 passed
  • py_compile ok
  • diff check ok

Would appreciate a maintainer review when someone has bandwidth. I think this is complementary to #33681 because it covers the safety-critical clarify case where Discord renders buttons but hides the embed body the user needs before choosing.

Duplicate the critical clarify prompt body into normal Discord message content while preserving the existing embed and button view. This keeps draft/approval text visible when Discord clients render components but hide the embed body.
@carltonawong
carltonawong force-pushed the fix/discord-clarify-visible-content branch from 6dcb9b2 to 924b461 Compare June 4, 2026 20:22
@carltonawong

Copy link
Copy Markdown
Contributor Author

Refreshed this branch on top of current main.

I also re-checked the related GitHub/source context before pushing:

The rebase conflict was only around current send_clarify() storing view._message; the refreshed branch keeps that behavior while adding the visible content fallback.

Validated after rebasing:

python -m pytest -o addopts='' tests/gateway/test_discord_clarify_buttons.py -q
python -m py_compile plugins/platforms/discord/adapter.py tests/gateway/test_discord_clarify_buttons.py
git diff --check origin/main...HEAD

Results:

  • 14 passed
  • py_compile ok
  • diff check ok

I also reran the prior red tests/hermes_cli/test_gui_command.py file locally; it still fails in my local environment due missing pathspec / desktop hash tests, which appears unrelated to this Discord clarify diff.

trevornk pushed a commit to trevornk/hermes-agent that referenced this pull request Jul 11, 2026
Discord clarify buttons put the (truncated) choice text directly on
the button label, relying on Discord's 80-char label cap plus a
word-boundary truncation algorithm. In practice this is still
unreadable: Discord mobile clients wrap/cut button text well before
80 chars (often <40 visible), so any truncation strategy on the
label itself still garbles longer choices regardless of how the cut
point is chosen.

PR NousResearch#54969 (merged as 87be36c) already fixed a related but
different bug in this same truncation path -- code-point slicing
instead of UTF-16 unit slicing, which could corrupt emoji-heavy
choice text at the cut boundary. That fix made the truncation
correct; this one removes the need for truncation at all.

Telegram and WhatsApp adapters already avoid this class of bug
entirely: button labels are just a short index, and the full choice
text is mirrored in the message body where there's no meaningful
length cap. This brings Discord's send_clarify() in line with that
same pattern:

- ClarifyChoiceView button labels are now just the option number
  ("1", "2", ...) instead of "1. <truncated text>". Removed the
  now-dead word/soft-boundary truncation logic for this path.
- send_clarify() renders the full, untruncated choice text as a
  numbered list in the embed's "Choices" field (1024-char cap,
  truncated only if genuinely absurd) and mirrors it again in the
  plain-text message content, matching the existing embeds-may-be-
  invisible-on-some-clients precaution already used elsewhere in
  this adapter.

Related: NousResearch#36186 (different bug in the same file -- clarify text
disappearing when Discord hides embed bodies entirely, not button
label truncation).

Review fixes (per hermes-sweeper automated review on PR NousResearch#62291):
- The embed field truncation only capped the option-list portion at
  1024 chars, then appended a ~65-char instruction suffix afterward --
  the combined value could reach ~1089 chars, over Discord's real
  1024-char embed-field limit, causing send_clarify() to fail on
  exactly the long-choice-list case this fix exists to handle. Now
  reserves suffix length before truncating so the combined field
  value never exceeds the cap. Added a boundary regression test with
  24 long choices asserting the rendered field stays <= 1024 chars
  and the suffix is never dropped.
- The plain-text message-content mirror now explicitly uses the
  *untruncated* option list (Discord's 2000-char content cap is much
  larger than the embed field's 1024), rather than reusing whatever
  the embed truncated to.
- Rebased onto a clean upstream main and dropped four unrelated
  fork-local commits (three explicitly tagged [carried], one
  untagged plugin symlink fix) that had accumulated on the source
  branch before this PR was cut -- this PR is Discord-only again.

Tests: tests/gateway/test_discord_clarify_buttons.py -- 5
truncation-behavior tests replaced with simpler "label is always
short" tests, 5 dict-unwrap tests updated to assert the full text
lands in the embed field rather than the button label, plus 1 new
boundary regression test for the field-cap fix. 21/21 pass. ruff
clean. git diff --check clean.
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused safety fallback. This is now implemented on current main by a broader Discord prompt-visibility fix.

  • Automated hermes-sweeper review verified plugins/platforms/discord/adapter.py:5816-5827: send_clarify() constructs normal content from the question and sends it alongside the existing embed and button view.
  • Commit 009b42d008b81c18af39414dded9ecdf06082d93 (fix(discord): mirror all interactive prompt payloads into message content) added this behavior and retained the embed as progressive enhancement.
  • tests/gateway/test_discord_prompt_content_siblings.py:69-104 covers both choice and open-ended clarify content fallbacks.
  • The implementation is contained in tag v2026.7.7.

Closing as implemented on main.

@teknium1 teknium1 closed this Jul 13, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists platform/discord Discord bot adapter sweeper:implemented-on-main Sweeper: behavior already present on current main type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants