Skip to content

feat: slash command handling with autocomplete in consumer UI#2

Merged
teng-lin merged 3 commits intomainfrom
feature/slash-commands
Feb 16, 2026
Merged

feat: slash command handling with autocomplete in consumer UI#2
teng-lin merged 3 commits intomainfrom
feature/slash-commands

Conversation

@teng-lin
Copy link
Copy Markdown
Owner

Summary

  • Consumer HTML now detects / prefix and sends slash commands as { type: "slash_command" } instead of user_message, enabling the existing bridge/executor pipeline from the browser
  • Adds autocomplete popup with keyboard navigation (arrow keys, Tab/Enter to select, Escape to dismiss, click to select)
  • Adds consumer-local /help and /clear commands that work without network
  • Improves slash_command_result rendering with command header + preformatted content block
  • Creates central command registry (slash-command-registry.ts) with categorized command definitions
  • Fixes overlap bug where /cost and /context were in both NATIVE_COMMANDS and EMULATABLE_COMMANDS

Test plan

  • npx vitest run — all 1108 tests pass (62 files, 0 failures)
  • Open consumer in browser, type / — autocomplete popup appears with all commands
  • Select /status via keyboard or click — see formatted status output with command header
  • Type /help — see grouped command list (consumer-local, no network round-trip)
  • Type /clear — messages cleared
  • Type /compact — forwarded to CLI as pass-through
  • Type a regular message — sent as user_message (unchanged behavior)
  • Escape with autocomplete open during running task — dismisses popup without sending interrupt

Consumer HTML now detects `/` prefix and sends slash commands as
`{ type: "slash_command" }` instead of `user_message`, enabling the
existing bridge/executor pipeline. Adds autocomplete popup with keyboard
navigation, consumer-local `/help` and `/clear` commands, improved
command result rendering, and a central command registry. Fixes overlap
where `/cost` and `/context` were in both NATIVE_COMMANDS and
EMULATABLE_COMMANDS.
- Add stopPropagation() to Escape handler so dismissing autocomplete
  doesn't also send an interrupt when a task is running
- Add hide() call in click handler so popup dismisses after selection
Apply truncate(content, 5000) in renderCommandResult, consistent with
peer methods that truncate tool results and inputs.
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @teng-lin, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the user experience in the consumer UI by introducing robust slash command functionality. Users can now easily discover and execute commands through an intuitive autocomplete interface, and benefit from immediate responses for common local actions. The changes streamline command processing, improve message rendering, and establish a clear, centralized system for managing all available commands.

Highlights

  • Slash Command Handling: The consumer UI now detects input starting with '/' as a slash command, routing it through the existing backend pipeline instead of as a user message.
  • Autocomplete Feature: An interactive autocomplete popup has been implemented for slash commands, supporting keyboard navigation (arrow keys, Tab/Enter to select, Escape to dismiss) and click selection.
  • Local Commands: New client-side '/help' and '/clear' commands are introduced, providing immediate feedback and actions without requiring network interaction.
  • Enhanced Command Result Display: The rendering of 'slash_command_result' messages has been improved with a distinct command header and preformatted content blocks for better readability.
  • Centralized Command Registry: A new 'slash-command-registry.ts' file centralizes command definitions, categorizing them into consumer, relay, and passthrough types for better management.
  • Command Categorization Fix: The overlap issue where '/cost' and '/context' were incorrectly listed in both 'NATIVE_COMMANDS' and 'EMULATABLE_COMMANDS' has been resolved, moving them to the 'relay' category.
Changelog
  • src/consumer/index.html
    • Added CSS styles for the new autocomplete popup and command result display.
    • Inserted a 'div' element for the autocomplete UI into the input bar.
    • Refactored message rendering calls to use public methods (e.g., 'renderStatus' instead of '_renderStatus').
    • Implemented 'SlashCommandHandler' and 'AutocompleteUI' classes to manage command logic and autocomplete display.
    • Integrated autocomplete functionality with the input field's 'input' and 'keydown' event listeners.
    • Added logic to 'sendMessage' to differentiate between user messages and slash commands, handling local commands ('/clear', '/help') and forwarding server commands.
    • Updated the 'message_history' case to set server commands via 'slashHandler.setServerCommands'.
  • src/consumer/renderer.ts
    • Modified the 'slash_command_result' message type handling to use the new 'renderCommandResult' method.
    • Simplified the 'renderStatus' method by removing redundant return logic.
    • Added a new 'renderCommandResult' method to format command output with a header and preformatted content.
  • src/core/slash-command-executor.test.ts
    • Updated 'isNativeCommand' tests to reflect the removal of '/cost' and '/context' from 'NATIVE_COMMANDS'.
  • src/core/slash-command-executor.ts
    • Removed '/cost' and '/context' from the 'NATIVE_COMMANDS' set to correct command categorization.
  • src/core/slash-command-registry.test.ts
    • Added a new test file to verify the functionality of the 'SlashCommandRegistry', including 'findCommand', 'getAllCommands', and ensuring unique command names and non-empty descriptions.
  • src/core/slash-command-registry.ts
    • Added a new file defining 'CommandCategory' and 'SlashCommandDef' types.
    • Introduced 'CONSUMER_COMMANDS', 'RELAY_COMMANDS', and 'PASSTHROUGH_COMMANDS' arrays to categorize all slash commands.
    • Provided 'findCommand' and 'getAllCommands' utility functions for command lookup.
Activity
  • The pull request was created by teng-lin.
  • The author provided a detailed summary and test plan in the pull request description.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@teng-lin teng-lin merged commit e491364 into main Feb 16, 2026
4 checks passed
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a robust slash command handling system in the consumer UI, including an autocomplete interface with keyboard navigation and centralized command definitions. The implementation correctly handles local commands like /help and /clear while forwarding others to the server. The addition of a central registry improves maintainability and ensures consistency between the UI and the backend executor. I have identified a few minor areas for improvement regarding input parsing edge cases and the robustness of the UUID fallback mechanism.

Comment thread src/consumer/index.html
const trimmed = input.trim();
const spaceIdx = trimmed.indexOf(' ');
if (spaceIdx === -1) return { name: trimmed, args: '' };
return { name: trimmed.slice(0, spaceIdx), args: trimmed.slice(spaceIdx + 1).trim() };
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The parse method assumes that the command name and arguments are separated by a single space. While trim() is called on the arguments, if the user input contains multiple spaces between the command and the first argument (e.g., /command arg), the current logic might include leading spaces in the args string before the final trim(). Although the final trim() handles this, a more robust approach would be to use a regular expression to split by one or more whitespace characters.

Suggested change
return { name: trimmed.slice(0, spaceIdx), args: trimmed.slice(spaceIdx + 1).trim() };
const parts = trimmed.split(/\s+/);
const name = parts[0];
const args = trimmed.slice(name.length).trim();
return { name, args };

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

This code was superseded by the Phase 2 rewrite (9f66855). The SlashCommandHandler class no longer exists in the consumer HTML.

Comment thread src/consumer/index.html
// Server slash command
const requestId = window.crypto.randomUUID
? window.crypto.randomUUID()
: `${Date.now()}-${Math.random()}`;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The fallback for randomUUID using Math.random() is not cryptographically secure. While likely sufficient for a request_id in this context, using a more robust unique identifier generation or ensuring the environment supports crypto.randomUUID is preferred for long-term reliability.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

This code was superseded by the Phase 2 rewrite (9f66855). The Math.random() fallback no longer exists — all UUID generation now uses crypto.randomUUID() directly.

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.

1 participant