Skip to content

fix(desktop): slash commands queued when busy and chip |0 suffix leak#39289

Merged
OutThisLife merged 1 commit into
mainfrom
fix/desktop-slash-commands
Jun 4, 2026
Merged

fix(desktop): slash commands queued when busy and chip |0 suffix leak#39289
OutThisLife merged 1 commit into
mainfrom
fix/desktop-slash-commands

Conversation

@ethernet8023

@ethernet8023 ethernet8023 commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Fixes two bugs in the desktop app's slash command handling compared to the TUI:

  1. Slash commands get queued instead of running immediately when the agent is busy. In the TUI, /yolo, /skin, /status, etc. execute instantly regardless of busy state. In the desktop composer, submitDraft() unconditionally queued any draft when busy && hasComposerPayload, forcing all slash commands to wait for the current turn to finish. This is wrong — most slash commands are client-side operations or self-contained gateway RPCs that don't need an idle session.

  2. Slash command chips show a |0 suffix. When selecting a slash command from the autocomplete popover, the trigger item's id includes a |index suffix for adapter uniqueness (e.g. /status|0). Because slash item metadata didn't include rawText/insertId, hermesDirectiveFormatter.serialize fell through to the legacy @${item.type}:${item.id} path, producing @slash:/status|0 — the |0 leaked into both the chip label and the submitted text.

Related Issue

Fixes #

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • apps/desktop/src/app/chat/composer/index.tsx — Added SLASH_COMMAND_RE check in submitDraft() before the queue branch. Slash commands (no attachments) bypass the queue and go straight to onSubmit()executeSlashCommand(), which has its own per-command busy guard.
  • apps/desktop/src/app/chat/composer/hooks/use-slash-completions.ts — Added rawText: command to slash item metadata so hermesDirectiveFormatter.serialize returns plain command text (e.g. /status) instead of @slash:/status|0. Slash commands now enter the composer as plain text, matching selectSkinSlashCommand and TUI behavior.

How to Test

  1. Start the desktop app with a provider configured
  2. Send a message that triggers a long-running tool call (e.g. a web search or code execution)
  3. While the agent is busy, type /status or /yolo and press Enter
  4. Before fix: the command is queued and waits for the turn to finish
  5. After fix: the command executes immediately (same as TUI)
  6. Clear the input, type / and select a slash command from the popover
  7. Before fix: the chip in the composer shows /status|0 (or the plain text contains |0)
  8. After fix: the composer shows /status as plain text, no |0 suffix

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
  • 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: NixOS

Documentation & Housekeeping

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

…x leak

Two fixes for desktop app slash command handling:

1. Slash commands submitted while the agent is busy now execute
   immediately instead of being queued. Previously submitDraft()
   unconditionally queued any draft when busy, but slash commands
   are client-side operations or self-contained gateway RPCs that
   should run regardless of busy state (matching TUI behavior).
   executeSlashCommand already has its own per-command busy guard
   for commands that genuinely need an idle session.

2. Slash command trigger items no longer leak the "|index" suffix
   from their item.id into the serialized chip text. The
   toItem callback now sets rawText in metadata so
   hermesDirectiveFormatter.serialize takes the direct-insertion
   path instead of the legacy @type:id fallback. This also means
   slash commands enter the composer as plain text (not chips),
   matching selectSkinSlashCommand and TUI behavior.
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: fix/desktop-slash-commands vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 9840 on HEAD, 9840 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5102 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@ethernet8023 ethernet8023 marked this pull request as draft June 4, 2026 21:00
@ethernet8023 ethernet8023 marked this pull request as ready for review June 4, 2026 21:01
@OutThisLife OutThisLife merged commit 1eeb7da into main Jun 4, 2026
20 checks passed
@OutThisLife OutThisLife deleted the fix/desktop-slash-commands branch June 4, 2026 21:06
davidgut1982 pushed a commit to davidgut1982/hermes-agent that referenced this pull request Jun 5, 2026
…x leak (NousResearch#39289)

Two fixes for desktop app slash command handling:

1. Slash commands submitted while the agent is busy now execute
   immediately instead of being queued. Previously submitDraft()
   unconditionally queued any draft when busy, but slash commands
   are client-side operations or self-contained gateway RPCs that
   should run regardless of busy state (matching TUI behavior).
   executeSlashCommand already has its own per-command busy guard
   for commands that genuinely need an idle session.

2. Slash command trigger items no longer leak the "|index" suffix
   from their item.id into the serialized chip text. The
   toItem callback now sets rawText in metadata so
   hermesDirectiveFormatter.serialize takes the direct-insertion
   path instead of the legacy @type:id fallback. This also means
   slash commands enter the composer as plain text (not chips),
   matching selectSkinSlashCommand and TUI behavior.
changman pushed a commit to changman/hermes-agent that referenced this pull request Jun 10, 2026
…x leak (NousResearch#39289)

Two fixes for desktop app slash command handling:

1. Slash commands submitted while the agent is busy now execute
   immediately instead of being queued. Previously submitDraft()
   unconditionally queued any draft when busy, but slash commands
   are client-side operations or self-contained gateway RPCs that
   should run regardless of busy state (matching TUI behavior).
   executeSlashCommand already has its own per-command busy guard
   for commands that genuinely need an idle session.

2. Slash command trigger items no longer leak the "|index" suffix
   from their item.id into the serialized chip text. The
   toItem callback now sets rawText in metadata so
   hermesDirectiveFormatter.serialize takes the direct-insertion
   path instead of the legacy @type:id fallback. This also means
   slash commands enter the composer as plain text (not chips),
   matching selectSkinSlashCommand and TUI behavior.
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.

2 participants