Skip to content

feat: interactive model picker with Discord Select UI and reasoning selector (#3710) - #3755

Closed
simplenamebox-ops wants to merge 8 commits into
NousResearch:mainfrom
simplenamebox-ops:feat/interactive-model-picker-discord
Closed

feat: interactive model picker with Discord Select UI and reasoning selector (#3710)#3755
simplenamebox-ops wants to merge 8 commits into
NousResearch:mainfrom
simplenamebox-ops:feat/interactive-model-picker-discord

Conversation

@simplenamebox-ops

@simplenamebox-ops simplenamebox-ops commented Mar 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds /models command with Discord Select menu UI and /model-status command. Addresses #3710.

New in latest commit: Gateway-level model override — /models no longer writes to config.yaml. Instead, it sets an in-memory override that persists across /new and session resets, clearing only on gateway restart. This restores the session-scoped switching behavior that was lost when /model was removed in 9783c9d.

How model switching works

Event Active model Config.yaml
Gateway start Loaded from config Unchanged
/models pick GLM-5 GLM-5 (in memory) Unchanged
/new or session reset GLM-5 (still in memory) Unchanged
Gateway restart Reloaded from config Unchanged

Config.yaml keeps the user's hard default. The picker switches the active model without touching it.

/model-status output

Model Status

Default (config.yaml): openai-codex/gpt-5.4
Active: ollama-cloud/glm-5 (via /models picker)
Last reply: glm-5
Cron: glm-5 (BTC Prediction - 4 hourly)

Key differences from #3718

  • Discord Select menus (native dropdowns) instead of text/button flow
  • Gateway-level override/models does NOT write config.yaml
  • Reasoning effort selector — none/low/medium/high/xhigh (persists to config)
  • /model-status — shows Default + Active + Last Reply + Cron
  • Guild-level slash sync — commands appear instantly
  • models.yaml catalog — user-curated per-provider model lists

Architecture

set_session_model()          ← /models picker sets this
    ↓
_resolve_gateway_model()     ← checks override first, then env, then config
    ↓
_resolve_runtime_agent_kwargs()  ← resolves provider from override
    ↓
AIAgent(model=..., **runtime)    ← uses active model

Files changed

File What
gateway/platforms/discord.py ModelPickerView + UI components + gateway override on submit
gateway/run.py set/get/clear_session_model(), model status, session info override label
hermes_cli/commands.py 2 CommandDef entries: models, model-status
hermes_cli/model_picker_config.py Catalog loader, provider config checker, formatting utils

Test plan

  • /models opens interactive picker with provider → model → reasoning dropdowns
  • Submit sets gateway override (config.yaml untouched)
  • Model persists across /new and session resets
  • Model reverts to config default on gateway restart
  • /model-status shows Default, Active (with source), Last Reply, Cron
  • Fallback indicator shows when primary model failed
  • Reasoning effort persists to config.yaml
  • Guild slash commands sync instantly on startup

🤖 Generated with Claude Code

Bitek added 2 commits March 29, 2026 18:09
…usResearch#3710)

Adds /models command with Discord Select menu dropdowns (not button/text flow),
/model-status showing configured vs actual vs cron models, and reasoning
effort selector in the picker.

- ModelPickerView: provider dropdown → model dropdown → reasoning dropdown → Submit
- Guild-level slash sync for instant command availability
- apply_model_selection() direct config write (no /model chat message interception)
- model_picker_config.py: models.yaml catalog loader with favourites support
- /model-status: shows configured, last-used (with fallback indicator), and cron models
@simplenamebox-ops
simplenamebox-ops force-pushed the feat/interactive-model-picker-discord branch from 7bfd2c9 to 5520f1b Compare March 29, 2026 17:21
Bitek and others added 6 commits March 29, 2026 21:50
Restores session-scoped model switching that was removed when /model was
deleted in 9783c9d.  The /models picker now sets a gateway-level override
instead of writing to config.yaml:

- Config keeps the user's hard default (survives gateway restarts)
- /models switches the active model in memory (survives /new, session
  resets, and idle timeouts — clears only on gateway restart)
- /model-status shows Default, Active (with source), Last Reply, and Cron

This matches the original /model behavior where users could switch models
without losing their configured default.

Changes:
- gateway/run.py: set_session_model/get_session_model/clear_session_model,
  _resolve_gateway_model checks override, _resolve_runtime_agent_kwargs
  checks override provider, _format_session_info shows override label,
  _handle_model_status_command shows Default + Active + Last Reply + Cron
- discord.py: apply_selection uses set_session_model() instead of
  apply_model_selection()

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Defer interaction immediately before resolve_runtime_provider() to avoid
  Discord's 3-second timeout (Unknown interaction 10062 error)
- Strip provider prefix from model ID (models.yaml uses "ollama-cloud/glm-5"
  but API expects "glm-5") — fixes 404 "model not found" and double-provider
  display in /model-status

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents "ollama-cloud/ollama-cloud/glm-5" when model ID from models.yaml
already contains the provider prefix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The model picker was blindly stripping everything before the first "/"
in model IDs, which breaks providers like Nous Portal (OpenRouter) where
model IDs use vendor/model format (e.g. "google/gemini-3.1-pro-preview").

Now only strips the prefix when it matches the selected provider ID
(e.g. "ollama-cloud/glm-5" → "glm-5" for ollama-cloud), preserving the
full ID for providers that need it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
/models was sending the picker view without deferring first, causing
Discord "Unknown interaction" errors when building the view took >3s.

/model-status was routed through the full agent message pipeline
(handle_message), which blocks behind any in-progress LLM call. Now
responds directly by reading config/state inline — instant response.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Exposes the runner's effective model via module-level get/set functions
(get_last_reply_model / set_last_reply_model) so the direct slash
command handler can display which model actually responded and whether
fallback was activated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/gateway Gateway runner, session dispatch, delivery platform/discord Discord bot adapter labels May 2, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #5742 (merged) which implemented an interactive model picker for Telegram and Discord. This PR adds Select menu UI and gateway-level override on top of that.

@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #5742 (merged) which implemented an interactive model picker for Telegram and Discord.

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the detailed picker implementation. This is now implemented on current main via the later merged PR #5742; the linked #3710 has also been closed as implemented.

  • 5a2cf280a shipped the Discord discord.ui.View Select-menu provider → model picker, plus the Telegram counterpart.
  • plugins/platforms/discord/adapter.py:5877 sends ModelPickerView; ModelPickerView builds the provider/model Select flow at :7180 and switches through its callback at :7364.
  • gateway/slash_commands.py:1480 invokes that picker for bare /model on capable gateway adapters and persists the resulting per-session override at :1620.
  • The later implementation intentionally scopes model selection per session. tests/gateway/test_session_model_reset.py:70 verifies /new clears only the initiating session's override, avoiding the PR's proposed process-global override affecting other gateway conversations.

This is an automated hermes-sweeper review.

@teknium1 teknium1 closed this Jul 12, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jul 12, 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 sweeper:implemented-on-main Sweeper: behavior already present on current main type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants