Skip to content

feat(discord): smart auto-thread mode (true/false/smart)#1054

Open
Hypn0sis wants to merge 2 commits intoRightNow-AI:mainfrom
Hypn0sis:feat/discord-smart-thread
Open

feat(discord): smart auto-thread mode (true/false/smart)#1054
Hypn0sis wants to merge 2 commits intoRightNow-AI:mainfrom
Hypn0sis:feat/discord-smart-thread

Conversation

@Hypn0sis
Copy link
Copy Markdown
Contributor

Summary

  • Adds auto_thread config field to DiscordConfig with three modes:
    • "true" — always create a thread from each message
    • "false" — never create a thread (default, opt-in)
    • "smart" — create a thread only when the bot is @mentioned
  • Thread name is derived from the message content (strips mention prefix, truncates to Discord's 100-char limit)
  • Auto-thread creation happens after all policy guards (group_policy, mention_only, free_response, rate-limit) so threads are never created for messages the bot would ignore
  • Incoming messages from inside a bot-created thread are detected and routed back into the same thread, preventing duplicate threads
  • MESSAGE_UPDATE events (Discord embed resolution) are deduplicated against already-forwarded MESSAGE_CREATE events to prevent double responses
  • Fixes api_send_thread_message to POST directly to channels/{thread_id}/messages (the correct Discord API endpoint for threads)
  • Adds RevoltAdapter::with_urls_and_channels constructor to support custom URLs + channel restrictions together

Config example

[channels.discord]
bot_token_env = "DISCORD_BOT_TOKEN"
auto_thread = "smart"   # or "true" / "false"

CI note

The Security Audit check may flag rustls-webpki 0.102 — that CVE is addressed in #1041 (already open). If that PR merges first, a rebase of this branch will clear the audit cleanly. The fix: clippy commit in this PR may also overlap with #1041's fixes to copilot.rs; a rebase will resolve any conflict trivially.

Test plan

  • cargo check --workspace --lib passes
  • cargo clippy --workspace --all-targets -- -D warnings passes
  • cargo test --workspace passes
  • Live: set auto_thread = "smart", @mention bot in server channel → thread created
  • Live: set auto_thread = "smart", message without @mention → no thread created
  • Live: set auto_thread = "false" → no threads ever created
  • Live: replies inside a bot-created thread stay in the thread (no new thread spawned)

Copy link
Copy Markdown
Member

@jaberjaber23 jaberjaber23 left a comment

Choose a reason for hiding this comment

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

Thanks for the Discord work @Hypn0sis. The auto-thread feature (true / false / smart) is useful and the core logic is reasonable, but this PR has a few issues that block merge.

Blockers

  1. threaded_message_ids.write().await.retain(|_| true) does nothing. In the THREAD_DELETE / CHANNEL_DELETE handlers you're calling retain(|_| true), which keeps every element — the comment says "prune message IDs for the deleted thread" but the closure always returns true. The dedup HashSet<MessageId> is therefore never pruned, and on a busy server it grows without bound. Either track a HashMap<ThreadId, HashSet<MessageId>> and drop the entry on thread delete, or put a size/time cap on the set.
  2. Scope creep — ~500+ lines of unrelated deploy tooling. deploy-remote.sh, sync-upstream-and-deploy.sh, .gitignore / CLAUDE.md changes are not about Discord smart-thread behavior. Please split them into a separate PR so this one can be reviewed on its own merits.
  3. CI — Security Audit: FAILURE. Your PR body points to #1041 for the rustls-webpki fix; now that #1041 is merged, please rebase and let CI re-run. Security Audit must be green before merge.

Concerns

  • In "true" mode the bot will create a thread per allowed message in group channels. Confirm this stays within Discord's rate limits on a hot channel (observed behavior at ~5–10 msg/s from multiple users).
  • #[allow(dead_code)] on the test helper — either use it or remove it.
  • regex_lite usage — confirm it's already a dependency and doesn't pull in a new transitive set.

Recommendation

Split the PR. Fix the retain(|_| true) bug and bound the dedup set. Rebase post-#1041. Re-request review and we'll land the Discord half quickly.

@Hypn0sis
Copy link
Copy Markdown
Contributor Author

CI update after force-push

Clippy is now fixed — 5 warnings in gemini.rs, openai.rs (×2), and session_repair.rs (×2) were introduced by upstream v0.5.10, not by this PR. Fixed in the latest push.

Regarding Security Audit: the two remaining advisories are pre-existing in main and unrelated to this PR:

  • RUSTSEC-2026-0097rand 0.9.2 unsoundness (transitive via tungstenite/axum/governor) — no fix available yet upstream
  • gimli 0.33.1 yanked (transitive via wasmtime 43)

Both were present on main before this branch was created. Happy to track them in a follow-up issue if needed.

@Hypn0sis Hypn0sis requested a review from jaberjaber23 April 17, 2026 21:13
pbranchu pushed a commit to pbranchu/openfang-upstream that referenced this pull request Apr 18, 2026
- RwLock: replace Arc<Mutex<String>> with Arc<RwLock<String>> for
  A2A_TASK_PROGRESS — eliminates exclusive lock in read-heavy path

- SSE parsing: extract pure parse_sse_data_line fn + SseLineOutcome enum;
  refactor both send_task_streaming and send_task_streaming_with_progress
  to use it; add timeout: Option<Duration> to both; 8 unit tests covering
  all outcomes (final, update, empty, malformed, error, unknown)

- Bounded maps: add MAX_CONCURRENT_ASYNC_TASKS=256 cap with clear error;
  AsyncTaskEntry{handle,inserted_at} tracks task age; OnceLock-based
  background sweep (10 min interval, 2 h TTL) aborts stale handles;
  TaskCleanupGuard RAII ensures cleanup on panic

- Prompt injection: rewrite inject_async_callback to deliver async results
  via structural ToolUse+ToolResult pair instead of text framing; remote
  agent content lands in a ToolResult block where LLM API semantics enforce
  the data boundary; add prepend_turns: Option<Vec<Message>> to both
  run_agent_loop and run_agent_loop_streaming so the synthetic ToolUse is
  inserted AFTER validate_and_repair (prevents orphan removal of the
  ToolResult user turn)

- Strip @default suffix from agent IDs in tool_agent_send (pre-existing fix)
- Update test to correctly verify prune_failed_tool_turns behavior

SSRF (RightNow-AI#1060): already using canonical crate::web_fetch::check_ssrf
Thread context (RightNow-AI#1054): context.thread_id passed through; will work
correctly once smart-thread sets it

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
matteodeagaziob52 and others added 2 commits April 20, 2026 09:31
…t mod

- Replace retain(|_| true) no-op with a size-capped clear: when
  threaded_message_ids exceeds MAX_DEDUP_MSG_IDS (2000) it is cleared.
  MESSAGE_UPDATE embed events arrive within seconds so old entries are
  always safe to discard; prevents unbounded growth on busy servers.
- Add #[cfg(test)] to mod tests so empty_threads() helper is only
  compiled in test mode — removes the need for #[allow(dead_code)].
@Hypn0sis Hypn0sis force-pushed the feat/discord-smart-thread branch from 8c4c78e to 0227ff1 Compare April 20, 2026 07:33
@Hypn0sis
Copy link
Copy Markdown
Contributor Author

CI update after rebase on v0.6.0

Rebased the branch onto current `main` (v0.6.0, commit `e6bab99`) as requested. The PR now contains only the two discord-relevant commits:

  • `525d7d8` — feat(discord): smart auto-thread mode (true/false/smart)
  • `0227ff1` — fix(discord): cap dedup set on thread delete, add `#[cfg(test)]` to test mod

All unrelated commits (deploy tooling, Clippy fixes for other crates) have been dropped — the scope creep concern is resolved.


On the remaining CI failures:

All three failing jobs are pre-existing regressions on `main` itself — not introduced by this PR. You can verify by checking the latest CI run on `main` directly: run 24637821654 shows the same Clippy, Format, and Security Audit failures on `main` with no PR involved.

Job Root cause Present on `main`?
Clippy `collapsible_match` in `openclaw.rs`, `gemini.rs`, `openai.rs` (×2); `sort_by` → `sort_by_key` in `session_repair.rs` (×2) — all in upstream code, not in discord files ✓ yes
Format `routes.rs`, `kernel.rs`, `cron_delivery.rs`, `config_injection.rs` and others need `cargo fmt` — upstream files, not touched by this PR ✓ yes
Security Audit `rand 0.9.2` (RUSTSEC-2026-0097) + `gimli 0.33.1` yanked — transitive via `tungstenite`/`axum`/`wasmtime` ✓ yes

Happy to include a fix-commit for the Clippy and Format regressions if that would help unblock the merge, but wanted to flag them as upstream issues first rather than silently expand scope again.

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.

3 participants