Skip to content

fix: derive slash command routing from session capabilities#7

Merged
teng-lin merged 3 commits intomainfrom
fix/slash-command-routing
Feb 16, 2026
Merged

fix: derive slash command routing from session capabilities#7
teng-lin merged 3 commits intomainfrom
fix/slash-command-routing

Conversation

@teng-lin
Copy link
Copy Markdown
Owner

Summary

  • Replace hardcoded NATIVE_COMMANDS set with getBackendCommands() that reads capabilities.commands / slash_commands from SessionState using three-tier fallback
  • Emulatable commands (/help, /model, /status, /config, /cost, /context) always win over native forwarding — instant local results, no round-trip
  • /help now shows rich capability descriptions when available, falls back to command names from slash_commands, and shows only emulatable commands before CLI connects

Test plan

  • npm test — all 1308 existing + 31 executor tests pass
  • npx tsc --noEmit — type check clean
  • Manual: start server, connect CLI, send /help — shows capabilities descriptions
  • Manual: send a command from capabilities not in old hardcoded list — forwards to CLI
  • Manual: send truly unknown command — "Unknown slash command" error

…f hardcoded list

Replace hardcoded NATIVE_COMMANDS set with getBackendCommands() that
reads capabilities/slash_commands from SessionState using three-tier
fallback (capabilities.commands → slash_commands → empty set).
Emulatable commands always win over native forwarding.
…guments

Addresses review findings: test empty capabilities.commands array
fallback to slash_commands, and verify commandName() extracts the
first token correctly when arguments are present.
Extract repeated command.split(/\s+/)[0] into commandName() helper.
Simplify emulator functions to use array literals instead of
push-then-join. Inline PTY runner callback to remove redundant
async wrapper.
@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 refactors how slash commands are routed and handled, moving from a static, hardcoded list to a dynamic system that leverages session capabilities. This change improves the flexibility and responsiveness of command execution by prioritizing local emulation for certain commands and providing more accurate information about available commands based on the connected backend's reported capabilities. The update enhances the user experience by making command discovery more intelligent and adaptable to different session states.

Highlights

  • Dynamic Slash Command Routing: Replaced the hardcoded list of native commands with a dynamic approach that derives available slash commands from the session's capabilities. This uses a three-tier fallback: capabilities.commands (authoritative), slash_commands (initial backend report), and an empty set if neither is available.
  • Emulatable Command Prioritization: Ensured that emulatable commands (e.g., /help, /model, /status) are always handled locally, providing instant results without a round-trip to the CLI, even if they are also reported by the backend.
  • Enhanced /help Command: Updated the /help command to display rich capability descriptions when available. It now falls back to showing command names from slash_commands and only lists emulatable commands before the CLI connects, offering a more informative and context-aware user experience.
Changelog
  • src/core/session-bridge.test.ts
    • Updated test cases to include slash_commands in makeInitMsg for simulating backend command reporting.
  • src/core/session-bridge.ts
    • Modified isNativeCommand and canHandle methods to accept SessionState as an argument, enabling dynamic command routing based on session capabilities.
  • src/core/slash-command-executor.test.ts
    • Added helper functions makeStateWithSlashCommands and makeStateWithCapabilities to simplify testing with different session states.
    • Introduced comprehensive tests for isNativeCommand and canHandle to validate capabilities-driven routing, fallback mechanisms, and emulatable command prioritization.
    • Added specific tests for the /help command's behavior under various capability reporting scenarios, including rich descriptions and fallbacks.
    • Refactored PTY disabled configuration into a constant for cleaner test code.
  • src/core/slash-command-executor.ts
    • Removed the hardcoded NATIVE_COMMANDS set.
    • Implemented commandName utility function to extract the base command from a full command string.
    • Introduced getBackendCommands function to dynamically derive backend-supported commands using a three-tier fallback logic (capabilities, slash_commands, empty set).
    • Updated the /help command's emulation logic to display rich descriptions from capabilities.commands or fall back to names from getBackendCommands.
    • Refactored isNativeCommand and canHandle to use the new getBackendCommands logic and explicitly handle emulatable commands.
    • Streamlined array initialization in /status, /config, /cost, and /context emulator functions.
Activity
  • The pull request author, teng-lin, has provided a detailed summary and test plan, indicating that unit tests (npm test, npx tsc --noEmit) have passed, and manual testing is planned for verifying the new command routing and /help command behavior.
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 6f7341f 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 refactors the slash command handling to derive command routing dynamically from session capabilities, removing the hardcoded NATIVE_COMMANDS set. The changes are well-implemented and thoroughly tested. The logic for command discovery with its three-tier fallback is sound. I've added a couple of suggestions to improve the user experience of the /help command by sorting the command list alphabetically for consistency.

Comment on lines 50 to 55
const allNames = [
...NATIVE_COMMANDS,
...Object.keys(EMULATABLE_COMMANDS).filter((name) => name !== "/help"),
...backendNames,
...Object.keys(EMULATABLE_COMMANDS).filter(
(name) => name !== "/help" && !backendNames.has(name),
),
];
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

To ensure a consistent and predictable order for the user, it's a good idea to sort the list of command names alphabetically.

Suggested change
const allNames = [
...NATIVE_COMMANDS,
...Object.keys(EMULATABLE_COMMANDS).filter((name) => name !== "/help"),
...backendNames,
...Object.keys(EMULATABLE_COMMANDS).filter(
(name) => name !== "/help" && !backendNames.has(name),
),
];
const allNames = [
...backendNames,
...Object.keys(EMULATABLE_COMMANDS).filter(
(name) => name !== "/help" && !backendNames.has(name),
),
].sort();

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.

Good catch — applied .sort() in 927f9ca on main. The /help fallback now lists commands alphabetically.

teng-lin added a commit that referenced this pull request Feb 16, 2026
Address Gemini Code Assist review comment on PR #7 — sort the
merged backend + emulatable command names for consistent ordering.
@teng-lin teng-lin deleted the fix/slash-command-routing branch February 16, 2026 18:26
teng-lin added a commit that referenced this pull request Feb 24, 2026
Fix architecture principle violations #1, #3, #4, #7:

- Fix #1: Remove dual lifecycle mutation by deleting applyLifecycleFromBackendMessage()
  which was redundant with reduceLifecycle()

- Fix #3: Make transitionLifecycle() private. Add SESSION_CLOSING system signal and
  route coordinator's direct calls through process()

- Fix #7: Route ConsumerGateway's backend:relaunch_needed emission through the
  runtime as BACKEND_RELAUNCH_NEEDED system signal instead of emitting directly

- Fix #4: Route BackendConnector's inline broadcasts and event emissions through
  the runtime via routeSystemSignal callback:
  - Part A: Connect/disconnect lifecycle (cli_connected, backend:connected, etc.)
  - Part B: Slash passthrough results/errors (slash_command_result, slash_command_error)

This enforces the core design principle that all state mutations flow through
SessionRuntime.process(), which dispatches to the pure reducer and executes effects.
All 2902 tests pass, typecheck clean.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
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