Skip to content

feat(discord): auto-rename generic thread titles - #33862

Open
kpadilha wants to merge 2 commits into
NousResearch:mainfrom
kpadilha:feat/discord-thread-autoname
Open

feat(discord): auto-rename generic thread titles#33862
kpadilha wants to merge 2 commits into
NousResearch:mainfrom
kpadilha:feat/discord-thread-autoname

Conversation

@kpadilha

@kpadilha kpadilha commented May 28, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Extends the existing guarded Discord semantic-title flow to pre-existing threads whose titles are generic, truncated, URL-heavy, or at Discord's title limit.

The feature remains opt-in (discord.auto_rename_threads.enabled: false). It does not add another title generator or rename path:

  • the inbound message and first successful assistant response feed Hermes' existing session-title generator;
  • existing durable session titles are reused without another model call;
  • the exact Discord title observed at ingress is serialized with the session source;
  • the existing rename_thread(..., only_if_current_name=...) guard prevents overwriting a human rename;
  • the existing UTF-16 helpers enforce Discord's title budget safely.

Hermes-created auto-threads already use this flow. This PR only opts pre-existing generic threads into it.

Related Issue

Related to #29983, #26477, #15757, #30559.

Type of Change

  • Feature
  • Documentation
  • Tests

Changes Made

  • Detect a narrow set of generic/truncated/noisy existing Discord thread titles.
  • Persist explicit auto_thread_rename_allowed provenance and the expected current title in SessionSource.
  • Reuse the current semantic session-title callback and guarded Discord rename_thread implementation.
  • Bridge discord.auto_rename_threads into Discord platform config.
  • Document the opt-in setting and Manage Threads permission.

Review Feedback Addressed

  • Candidate generation now starts from the inbound message through the existing semantic-title flow; the generic current title is never used as the candidate.
  • No code-point title slicing was added; the current UTF-16-aware rename helper is reused.
  • Provenance is serialized, and rename is conditional on the exact expected current name.
  • Regression coverage includes the enabled nova thread path, serialization, existing durable titles, config bridging, and human-name preservation.

Validation

531 passed, 1 skipped, 2 pre-existing warnings
ruff: all checks passed
git diff --check: clean
py_compile: passed

Checklist

  • Current upstream main used as base
  • Focused and Discord-adjacent tests pass
  • Documentation updated
  • Contributor-safe GitHub noreply author identity

@alt-glitch alt-glitch added type/feature New feature or request comp/plugins Plugin system and bundled plugins platform/discord Discord bot adapter P3 Low — cosmetic, nice to have labels May 28, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to existing Discord thread title work: #29983 (auto-rename + periodic retitle), #15757 (sync thread names with session titles), #18430 (tracking issue). This PR takes a more conservative approach — deterministic heuristics only, no model call, opt-in by default.

@Morad37

Morad37 commented May 28, 2026

Copy link
Copy Markdown
Contributor

The cleanup regexes look solid. One thing that tripped me up on a similar project: Discord thread names from forum channels can include trailing ellipsis or truncation markers that arent caught by the edge regex. Worth checking if theres a title.length > 80 scenario where Discord silently truncates, leaving a partial word + ... that survives the cleanup.

@kpadilha
kpadilha force-pushed the feat/discord-thread-autoname branch from 7925831 to 1d6fd3a Compare May 28, 2026 15:16
@kpadilha

Copy link
Copy Markdown
Contributor Author

Addressed the truncation edge case called out above:

  • added an explicit trailing-truncation marker regex for ..., , , and instead of relying only on the generic edge cleanup;
  • strip those markers during title cleanup so regenerated names do not retain truncation punctuation;
  • added coverage for Unicode ellipsis truncation and Discord max-length partial titles.

Also rewrote the commit author to a GitHub noreply address so the contributor-attribution check should stop failing on niko@hermes.local.

Local validation after the update:

pytest tests/gateway/test_discord_thread_autoname.py -q
# 11 passed

pytest tests/gateway/test_discord_thread_autoname.py tests/gateway/test_discord_thread_persistence.py tests/gateway/test_discord_connect.py tests/test_gateway_streaming_nested_config.py -q
# 38 passed

pytest tests/gateway/test_discord_*.py tests/test_gateway_streaming_nested_config.py -q
# 373 passed, 2 pre-existing warnings

@kpadilha
kpadilha force-pushed the feat/discord-thread-autoname branch from 1d6fd3a to fe7495f Compare June 8, 2026 12:57
@kpadilha
kpadilha marked this pull request as ready for review June 8, 2026 12:57
@kpadilha
kpadilha force-pushed the feat/discord-thread-autoname branch from fe7495f to 3feb16a Compare June 8, 2026 13:03

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the conservative, opt-in approach. Current main now has a narrower semantic-title flow for newly Hermes-created threads, but this PR remains distinct because it targets pre-existing generic titles.

Problems

  • plugins/platforms/discord/adapter.py:794-796 passes current_name before message content; the helper selects its first usable input at line 230. An enabled nova thread therefore becomes only Nova thread, not a title derived from the message. The added tests do not cover that enabled generic-title path.
  • plugins/platforms/discord/adapter.py:149-156 uses code-point slicing. Current main changed Discord thread title truncation to UTF-16-aware helpers in commit 1deeaf71a (plugins/platforms/discord/adapter.py:5417-5421), so this would reintroduce an emoji boundary bug.
  • The write at proposed line 801 can affect any existing parented thread matched by a heuristic. Current main deliberately limits renames to recorded Hermes-created threads and checks the original title before editing (gateway/run.py:13647-13692).

Suggested changes

  • Prefer inbound message text for the candidate and add a generic-title regression test.
  • Reuse the UTF-16 truncation helpers.
  • Add durable provenance plus an expected-current-name guard, or narrow the feature to Hermes-created threads.

Automated hermes-sweeper review.

Comment thread plugins/platforms/discord/adapter.py Outdated

def _discord_truncate_thread_title(title: str, max_length: int = _DISCORD_THREAD_TITLE_MAX_LENGTH) -> str:
title = _discord_clean_thread_title_text(title)
if len(title) <= max_length:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Discord thread-name limits are measured in UTF-16 code units, not Python code points. Current main uses utf16_len and _prefix_within_utf16_limit for this path (plugins/platforms/discord/adapter.py:5417-5421); please reuse those helpers so emoji cannot exceed the configured wire budget.

Comment thread plugins/platforms/discord/adapter.py Outdated
if not should_rename:
return False
title = _discord_thread_title_from_messages(
[current_name, str(getattr(message, "content", "") or "")],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This order prevents a generic title from being replaced by message content: _discord_thread_title_from_messages() always uses its first usable input. For example, nova thread becomes only Nova thread. Pass meaningful inbound content first and add an enabled generic-title regression test.

Comment thread plugins/platforms/discord/adapter.py Outdated
if not title or title == current_name:
return False
try:
await channel.edit(name=title, reason="Hermes auto-renamed generic Discord thread title")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This edits any pre-existing thread that the heuristic classifies. Current main protects manual/pre-existing names by restricting semantic renames to provenance-marked Hermes-created threads and requiring the recorded initial name to still match. Please add an equivalent ownership/current-name guard before writing.

@kpadilha
kpadilha force-pushed the feat/discord-thread-autoname branch from 3feb16a to c65da59 Compare July 13, 2026 17:33
@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026
@alt-glitch alt-glitch added the comp/gateway Gateway runner, session dispatch, delivery label Jul 13, 2026
@kpadilha

kpadilha commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review — addressed on the refreshed branch.

  • Removed the parallel deterministic title path; opted-in existing generic threads now reuse the current semantic session-title flow, so the candidate comes from the inbound exchange (or an already persisted session title), never from the generic current name.
  • Reused the existing UTF-16-safe title sanitizer and rename_thread(..., only_if_current_name=...) guard.
  • Added serialized auto_thread_rename_allowed provenance plus the exact expected current name.
  • Added enabled-path regression coverage for nova thread, explicitly asserting that the inbound message is passed to title generation; also added UTF-16 emoji-boundary and human-rename guard coverage.

Validation: 531 Discord-adjacent tests pass; all required CI checks are green.

@kpadilha
kpadilha force-pushed the feat/discord-thread-autoname branch 3 times, most recently from 5da6d5f to 9f28724 Compare July 13, 2026 18:41
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 comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have platform/discord Discord bot adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants