fix(discord): register slash commands globally only#804
Conversation
Review: fix(discord): register slash commands globally onlyVerdict: REQUEST_CHANGES 🔴 BLOCKING殘留 guild commands 未清理 — Discord guild-level commands 是 server-side 持久化的,移除註冊代碼不等於刪除已存在的 guild commands。所有跑過舊版的 guild 仍會看到重複命令。需在 ready handler 中補一段一次性清空邏輯: // One-time cleanup: remove stale guild-level commands left by older versions.
for guild in &ready.guilds {
let guild_id = guild.id;
if let Err(e) = guild_id.set_commands(&ctx.http, vec![]).await {
tracing::warn!(%guild_id, error = %e, "failed to clear stale guild slash commands");
}
}若已通過其他途徑(手動 / script)確認所有 guild 已清理,請在 PR description 說明。 🟡 NITSource-grep test 脆弱 — 🟢 INFOGlobal commands 傳播延遲(最長 ~1h)是已知取捨,註釋已說明,無需額外處理。 |
|
Supplementary note: before merging, please verify:
This confirms both the fix and the migration path are complete. |
Register Discord slash commands only at global scope so the same commands are not also created per guild. This keeps slash commands available in DMs and prevents duplicate entries in guild command pickers.
86eeb0d to
8d98856
Compare
|
Addressed the review feedback in the latest push:
Validation available in this environment:
Not run here:
|
|
Re-reviewed after latest push. Changes verified locally:
Minor style fix applied: Blocking issue resolved — guild-level commands are now properly cleared on startup. LGTM. |
wangyuyan-agent
left a comment
There was a problem hiding this comment.
Verified: compiles cleanly, clippy passes, blocking issue addressed. Approving.
masami-agent
left a comment
There was a problem hiding this comment.
PR Review: #804
Reviewed commit: 8d98856
Summary
- Problem: Discord shows duplicate slash commands because OpenAB registers them both globally and per-guild.
- Approach: Register globally only + clear stale guild commands as migration cleanup.
- Risk level: Low
Core Assessment
- Problem clearly stated: ✅ — Clear description with before/after diagram
- Approach appropriate: ✅ — Matches Discord documented behavior (global commands work in DMs + guilds)
- Alternatives considered: ✅ — Four alternatives listed with rejection reasons
- Best approach for now: ✅ — Minimal change, correct semantics
Findings
🟢 INFO
- The fix is clean and minimal — only touches the
ready()handler insrc/discord.rs - Good that the PR clears guild commands with
Vec::new()rather than just removing the loop — this handles the migration case where old guild commands are already persisted server-side by Discord - Single commit, conventional commit format ✅
- CI passes ✅
🟡 NIT
-
Missing success log for guild cleanup — The old code logged success per guild. The new code only logs on failure. Consider adding a
tracing::debug!on success for observability during the migration period:} else { tracing::debug!(%guild_id, "cleared stale guild slash commands"); }
Not a blocker — this is a one-time cleanup operation.
-
Migration cleanup runs every restart — The
Vec::new()call happens on everyready()event, not just once. This is harmless (idempotent) but slightly wasteful after the first run. Acceptable for simplicity — could be removed in a future version.
🔴 SUGGESTED CHANGES
- None.
Verdict: APPROVE
Clean, well-scoped bug fix. The approach is correct — global-only registration avoids duplicates while maintaining DM support, and the guild cleanup handles the migration path for existing deployments. No blocking issues.
PR Review (Stage 2 — Second Review): #804Reviewed at commit: Summary
Prior Review Verification
Both reviews are correct. I agree with their assessments. Core Assessment
Findings🟢 INFO
🟡 NIT
🔴 SUGGESTED CHANGES
Verdict: APPROVETextbook bug fix — correct diagnosis, minimal change, proper migration handling, well-documented. No issues. @jacklau1993 Clean work. 👍 |
obrutjack
left a comment
There was a problem hiding this comment.
Clean bug fix. Global-only registration is correct, migration cleanup handles existing deployments. Approved.
What problem does this solve?
Discord slash commands were registered twice for guild users: once as global commands and once again as guild-specific commands during
ready(). Discord shows both command scopes in guild command pickers, so users can see duplicate/models,/agents,/cancel,/cancel-all,/reset, and/remindentries.Discord Discussion URL: https://discord.com/channels/1491295327620169908/1491365157010542652/1503874520128295072
At a Glance
Prior Art & Industry Research
Not applicable — this is a narrow Discord adapter bug fix. It removes duplicate registration of the same slash commands and adds a migration cleanup for stale Discord guild commands. It does not introduce architectural, runtime, agent, scheduling, delivery, or persistence design changes.
OpenClaw: Not researched because prior-art research is not required for this trivial bug fix.
Hermes Agent: Not researched because prior-art research is not required for this trivial bug fix.
Proposed Solution
Register Discord slash commands with
Command::set_global_commands()so commands remain available in DMs and all guilds.During
ready(), overwrite each guild's command set with an empty list usingguild_id.set_commands(&ctx.http, Vec::new()). This clears guild-specific commands left behind by older OpenAB versions, because Discord persists guild commands server-side after registration.The source-grep regression test from the initial PR revision was removed because the cleanup path legitimately calls
set_commands()to delete stale guild commands.Why this approach?
Global command registration matches the desired behavior because OpenAB supports Discord DMs. Guild-specific registration would make commands appear faster in guilds, but it cannot support DMs and causes duplicates when used alongside global registration.
Clearing guild command sets in
ready()handles deployments that already ran the old version. Without this migration cleanup, removing the old registration loop would stop creating new duplicates but would not remove guild commands already persisted by Discord.Tradeoff: global command updates can take time to propagate through Discord. That is preferable to duplicate user-facing commands and keeps DM support intact.
Alternatives Considered
Validation
git diff --checkpassescargo checkpasses — not run because this environment does not havecargoinstalledcargo testpasses — not run because this environment does not havecargoinstalledcargo clippyclean — not run because this environment does not havecargoinstalled