Skip to content

[Bug]: TUI /model with trailing space skips ModelPicker, custom providers missing from completions #13621

@cutelele

Description

@cutelele

Bug Description

Two related issues with the /model command in TUI (hermes --tui):

1. /model (with trailing space) skips ModelPicker

When typing /model and pressing Enter, the TUI autocomplete system appends a space, turning the input into /model . The current logic in session.ts checks if (!arg), but arg is now " " (a space string), which is truthy. This causes it to skip the ModelPicker and fall through to config.set, which fails silently.

Fix: Change if (!arg) to if (!arg || !arg.trim()) at ui-tui/src/app/slash/commands/session.ts:67.

2. Custom providers missing from /model completions

SlashCommandCompleter._model_completions() only yields completions from model_aliases (config) and MODEL_ALIASES (built-in). Models defined under custom_providers in config.yaml are completely absent from the autocomplete list.

Fix: After yielding built-in aliases, also iterate custom_providers from config and yield their models as completions.

Reproduction

  1. Configure custom_providers in ~/.hermes/config.yaml
  2. Start hermes --tui
  3. Type /model and press Enter → expected: ModelPicker opens; actual: nothing happens (or falls through)
  4. Type /model → custom provider models are not in the completion list

Environment

  • Hermes Agent: 0.10.0 (2026.4.16)
  • Platform: Linux (OrbStack VM)
  • TUI mode

Suggested Patches

session.ts (line 67)

-      if (!arg) {
+      if (!arg || !arg.trim()) {

commands.py (_model_completions, after built-in aliases loop)

# Custom providers from config.yaml
try:
    from hermes_cli.config import load_config
    cfg = load_config()
    custom_providers = cfg.get("custom_providers") if isinstance(cfg.get("custom_providers"), list) else []
    for entry in custom_providers:
        if not isinstance(entry, dict):
            continue
        provider_name = (entry.get("name") or "").strip()
        if not provider_name:
            continue
        models = entry.get("models")
        if isinstance(models, dict):
            model_ids = list(models.keys())
        elif isinstance(models, list):
            model_ids = list(models)
        else:
            default_model = (entry.get("model") or "").strip()
            model_ids = [default_model] if default_model else []
        for mid in model_ids:
            mid_stripped = mid.strip()
            if not mid_stripped or mid_stripped in seen:
                continue
            seen.add(mid_stripped)
            if mid_stripped.lower().startswith(sub_lower):
                yield Completion(
                    mid_stripped,
                    start_position=-len(sub_text),
                    display=mid_stripped,
                    display_meta=f"custom:{provider_name.lower().replace(' ', '-')}",
                )
except Exception:
    pass

Metadata

Metadata

Assignees

No one assigned

    Labels

    comp/tuiTerminal UI (ui-tui/ + tui_gateway/)type/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions