Skip to content

feat(discord): sync thread names from session titles - #57679

Closed
yshen92 wants to merge 1 commit into
NousResearch:mainfrom
yshen92:fix/discord-session-title-thread-sync
Closed

feat(discord): sync thread names from session titles#57679
yshen92 wants to merge 1 commit into
NousResearch:mainfrom
yshen92:fix/discord-session-title-thread-sync

Conversation

@yshen92

@yshen92 yshen92 commented Jul 3, 2026

Copy link
Copy Markdown

What does this PR do?

Fixes #18430.

Hermes-created Discord threads already get generated session titles, but the visible Discord thread name stays as the original user-message snippet. That makes Discord's native thread list hard to scan because threads keep cryptic or truncated names even after Hermes has a better session title.

This PR syncs Hermes-generated session titles to visible Discord thread names, behind an opt-in config gate. It reuses the existing session-title flow and the existing maybe_auto_title(..., title_callback=...) seam. It does not add a new model tool, model schema, or environment variable.

Mapping to #18430

Issue requirement Where implemented
Config option to enable the behavior discord.auto_rename_threads.enabled, default false
Detect title generation after maybe_auto_title Existing title_callback seam; agent/title_generator.py untouched
Sanitize/truncate to Discord's 100-char thread-name limit Gateway sanitizer plus adapter-level cap (defense in depth); values above 100 clamped
Graceful failure without permissions / archived threads Three-layer error isolation; a rename failure cannot interrupt response delivery
Guardrail: conservative default (off) Disabled by default; zero behavior change for existing deployments
Guardrail: /title renames only behind a separate option sync_title_command, default false (requires enabled: true and mode: session_title)
Guardrail: don't overwrite manually renamed threads Not implemented in this PR — see Limitations

Limitations

This PR renames the thread whenever a session title is generated while the feature is enabled; it does not detect that a user manually renamed the thread in the meantime. This is a deliberate scope cut to keep the diff minimal and avoid per-thread initial-name state. If maintainers want the guard in this PR, I'm happy to add an initial-name check as a follow-up commit; #35420's thread_initial_name approach shows one viable shape.

Relationship to existing Discord thread-title PRs

Several PRs target #18430 or adjacent thread-naming behavior. This PR is the narrow, strictly opt-in implementation of the issue's proposed solution.

So the claim is not "nobody has proposed this." The claim is "this is the current, tested, strictly opt-in implementation matching the issue's proposed guardrails, with the smallest blast radius of the open attempts."

Related Issue

Fixes #18430

Related: #35420, #15757, #29983, #26477, #30559, #13915, #3009, #33862

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • gateway/run.py
    • Detects Discord thread lanes and schedules best-effort title sync through the existing generated-title callback path.
    • Keeps response delivery isolated from Discord rename failures.
  • plugins/platforms/discord/adapter.py
    • Adds DiscordAdapter.rename_thread(thread_id, name).
    • Resolves thread/channel IDs with get_channel first and fetch_channel fallback.
    • Handles invalid IDs, permission/API errors, archived/locked threads, and unexpected exceptions without propagating into the response path.
  • gateway/slash_commands.py
    • Extends /title Name so manual session titles can also sync the visible Discord thread name when explicitly enabled.
    • Leaves read-only /title behavior unchanged.
  • gateway/config.py, hermes_cli/config.py, cli-config.yaml.example
    • Adds discord.auto_rename_threads config with disabled defaults:
discord:
  auto_rename_threads:
    enabled: false
    mode: session_title
    sync_title_command: false
    max_length: 100
  • website/docs/user-guide/messaging/discord.md
    • Documents the opt-in config, /title coupling, 100-character Discord name cap, and rate-limit considerations.
  • Tests
    • Adds Discord title-sync coverage, /title coverage (including a test that exercises the real /title → scheduler → adapter path, RED on pre-fix code), config-default coverage, adversarial cases (invalid thread IDs, missing adapter/client, cache-miss fetch fallback), and regression checks for existing Discord/Telegram behavior.

How to Test

Automated checks run locally:

scripts/run_tests.sh \
  tests/gateway/test_discord_thread_title_rename.py \
  tests/gateway/test_title_command.py \
  tests/test_gateway_streaming_nested_config.py \
  tests/gateway/test_discord_slash_commands.py \
  tests/gateway/test_telegram_topic_mode.py

Result:

122 passed, 0 failed

Syntax check:

python -m py_compile \
  gateway/run.py \
  gateway/slash_commands.py \
  gateway/config.py \
  hermes_cli/config.py \
  plugins/platforms/discord/adapter.py

Result:

PASS

Manual rollout check performed on a Discord gateway instance after enabling:

discord:
  auto_rename_threads:
    enabled: true
    mode: session_title
    sync_title_command: true
    max_length: 100

Verified behavior:

  1. A newly created Discord auto-thread was renamed from the initial message snippet to the generated Hermes session title.
  2. /title Manual English Title updated both the stored Hermes session title and the visible Discord thread name.
  3. Gateway stayed active after restart and did not report fatal rename errors.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate (see Relationship section)
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: Ubuntu/Linux gateway service with Discord enabled

Note: I ran the targeted gateway/config regression suite above, not the full pytest tests/ -q suite.

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Screenshots / Logs

No screenshots attached to keep the PR focused on code and tests.

Relevant verification summary:

122 passed, 0 failed
py_compile PASS
gateway rollout verified locally with Discord thread rename and /title rename

Privacy/data guardrails

  • No outbound telemetry, analytics, or third-party identifier tagging.
  • Uses the existing Discord bot token already configured for the gateway. No new credentials.
  • Session title generation behavior is unchanged and stays in the existing agent/title_generator.py path.
  • No user PII is sent beyond what the bot already sends in normal Discord message delivery.
  • Config defaults are disabled, so no existing Discord server is affected unless an operator explicitly opts in.
  • No .env variable added. Behavioral config lives in config.yaml.

Add Discord thread title sync from Hermes-generated session titles behind config (discord.auto_rename_threads). Disabled by default; when enabled, session title callbacks and optional /title sync rename visible Discord thread names via DiscordAdapter.rename_thread.

- Gateway: _is_discord_thread_lane, _sanitize_discord_thread_title, _schedule_discord_thread_title_rename wired through existing maybe_auto_title title_callback seam
- Adapter: DiscordAdapter.rename_thread with get_channel/fetch_channel fallback, permission/archive error handling, and no raises to response delivery
- Config: discord.auto_rename_threads.enabled/mode/sync_title_command/max_length defaults, no new env var
- /title sync gated by sync_title_command + enabled + mode=session_title + Discord thread source; scheduler called directly from the async handler
- Tests: 22 new test cases; 122-test targeted suite green across affected files and regressions
- Docs: discord.md and config example document command-sync coupling, 100-character clamp, and Discord rate-limit behavior

Refs: NousResearch#18430, NousResearch#33862
@alt-glitch alt-glitch added type/feature New feature or request comp/gateway Gateway runner, session dispatch, delivery platform/discord Discord bot adapter P3 Low — cosmetic, nice to have labels Jul 3, 2026
@yshen92
yshen92 marked this pull request as ready for review July 3, 2026 14:42
@teknium1

teknium1 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Fixed via #60187 (salvage of #56792 by @rungmc357). We went with the default-on, guard-based approach (matching how Telegram topic rename shipped) over a config gate. Thanks for the thorough config plumbing and tests!

@teknium1 teknium1 closed this Jul 7, 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 P3 Low — cosmetic, nice to have platform/discord Discord bot adapter type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(discord): auto-rename threads from generated session titles

3 participants