Slash Command Architecture
Document type: Architecture and evolution conventions — describes "single source of truth", layering boundaries, and implementation principles. Relationship to other docs: See
SlashCommands.mdfor the command reference table;CLI.mdfor the CLI command list. This document does not enumerate all commands — it defines how they are organized and how to prevent drift.
1. Background & Problem
Slash-prefixed commands (/) are currently implemented in multiple places:
- Gateway:
MessageHandler._handle_channel_controlhandles/new_session,/mode …, etc. on controlled channels, deciding whether to intercept and NOT forward to Agent. - IM Pipeline / Channels: e.g.
gateway/im_pipeline/im_inbound.pymaintains its own control message set; Feishu/WeCom channels may have text-based checks that diverge from the main logic. - CLI TUI:
jiuwenswarm/channels/tui/frontend/src/core/commands/has a local registry; some commands call the backend via WebSocket, others are purely local.
Without clear layering and a single source of truth, the project risks: semantic inconsistencies for the same command name, documentation-code drift, and duplicated parsing logic in new channels.
2. Design Goals
| Goal | Description |
|---|---|
| Single Source of Truth (SSOT) | For gateway-controlled slash commands, the command name, valid forms, and match semantics should be defined in one place. Other modules reference rather than copy. |
| Clear Boundaries | Distinguish "Gateway-only", "Client-only", and "Name-aligned, execution-split" categories. Avoid stuffing all product slash commands into a single Gateway module. |
| Evolvable | Adding a new controlled channel only requires checking the registry and _control_channel_types policies. |
| Consistent with REPL conventions | Local-UI slash commands (help, diagnostics) are resolved client-side first; unrecognized /xxx should NOT be forwarded as plain user content by default (see REPL design doc). |
2.1 Non-goals
- All slash commands need NOT be executed in the Python Gateway (CLI-exclusive commands remain client-side).
- A single big-bang refactor is not required; incremental migration of constants and parsing to SSOT is acceptable.
3. Three-Layer Classification (Mandatory)
3.1 Category A: Gateway Channel Control
Definition: User messages arriving at the Gateway that are identified by MessageHandler (or its unified entry point), potentially only changing session/mode/routing without entering Agent conversation.
Typical commands: /new_session, /mode agent|code|team and /switch plan|fast|normal on controlled channels, plus direct forms like /mode agent.plan|agent.fast|code.plan|code.normal (per current implementation).
Requirements:
- Valid forms, match semantics (exact / prefix / multiline), and error messages should be described by the SSOT.
im_inboundand IM channels that need pre-filtering must import the same SSOT — private subset copies are prohibited. - Registry entries must specify applicable channel types (aligned with
_control_channel_typesand_session_map_channel_types), avoiding blanket "all channels" defaults.
3.2 Category B: Client-Only
Definition: Commands parsed and executed locally in CLI TUI, Web REPL, etc., or commands that should NOT be semantically intercepted by the Gateway.
Typical commands: UI toggles, /resume, /model (if purely local config), help/diagnostic stubs — per CLI.md.
Requirements:
- NOT included in the Gateway intercept table as the sole truth. If backend mode alignment is needed, use existing protocol fields (e.g.
params.mode), not re-parsing CLI aliases in the Gateway. - Document the processing process: Node CLI / browser frontend, etc.
3.3 Category C: Name-Aligned, Execution-Split (Hybrid)
Definition: Commands where the name and help text should be consistent across CLI and IM, but execution spans client + backend (e.g. local validation then RPC).
Requirements:
- Add
canonical_name+cli_aliasfields in the SSOT or doc matrix, so name mismatches are traceable. - The Gateway need NOT understand CLI aliases; if future server-side recognition is needed, add it as a new requirement and extend the protocol explicitly.
4. Single Source of Truth (SSOT) — Proposed Shape
4.1 Module Location (Proposed)
- Python side: Implemented as
jiuwenswarm/gateway/slash_command.py(controlled channel parsing,CONTROL_MESSAGE_TEXTS, first-batch command metadataFIRST_BATCH_REGISTRY). May evolve intochannel_control_slash.pyetc.- Data: The set of controlled commands, match rules (exact / prefix / no-multi-line), metadata (description, whether to forward to Agent).
- Pure functions: Given a channel type and user text, return a structured decision (not hit / hit & valid / hit & invalid). No IO in SSOT module (no
create_taskfor notifications).
- Naming suggestion: If only containing Category A, the module name should avoid suggesting "all product slashes", preventing future contributors from stuffing Category B logic into the Gateway.
4.2 Registry Minimum Fields (Proposed)
| Field | Description |
|---|---|
id |
Stable internal identifier (e.g. new_session, mode_switch). |
patterns |
Valid user input forms (including whether to match whole-line only). |
scope |
gateway (this design's scope). |
channels |
all_controlled or explicit list, aligned with config channel types. |
intercept |
Whether to withhold from Agent when hit and valid (per _handle_channel_control semantics). |
notes |
Cross-reference to CLI aliases and doc anchors (links to CLI.md sections). |
4.3 Relationship to MessageHandler
- Parsing & decision: Call the SSOT module, reducing inline
startswithchains inmessage_handler.py. - Side effects: Still in
MessageHandler(or a dedicated service class) for task cancellation, notification dispatch, etc. — avoiding async side effects in the "table module" for testability.
5. How Each Entry Point Integrates (Principles)
| Entry Point | Principle |
|---|---|
Gateway MessageHandler |
Before controlled-channel user text enters unified control logic, use SSOT for decisions. |
im_inbound etc. |
If pre-filtering or statistics are needed, import the same constants/functions — no independent frozenset subsets. |
| Feishu / WeCom etc. | If lightweight pre-checking is needed at the Channel layer, reuse SSOT or only do coarse "might be a control command" filtering. Final semantics always per Gateway. If dual-point checking exists, document in registry notes and load-test to avoid duplicate prompts. |
| CLI | Continue maintaining the TS registry; align names with Category A per CLI.md and §3.3 above. Do NOT duplicate Category B logic in the Gateway. |
6. "Unknown Slash" Protocol Conventions
- Client (REPL/TUI): Input starting with
/should go through the local command router first. Unrecognized commands should prompt the user and NOT be sent as plain conversation content (per product UX). - Gateway: Only guarantees SSOT-based handling of Category A for channels that actually reach the Gateway. Does not need to recognize all CLI-only commands.
7. Testing & Quality Assurance
- Provide unit tests for the SSOT: cover exact match, illegal suffix, multiline text,
/modefirst-level vs. direct-value forms,/switchvalid/invalid combos, etc. — consistent with production behavior. - Regression note: SessionMap channel family vs. regular controlled channels'
session_idbehavior is still managed by the existing state machine. SSOT only addresses string-level consistency and maintainability.
8. Phased Implementation (Proposed)
| Phase | Content |
|---|---|
| P0 | Extract Category A commands into SSOT module; im_inbound etc. switch to imports, eliminating set drift. |
| P1 | Converge inline parsing in message_handler.py to SSOT calls; behavior unchanged. |
| P2 | Fill in Category B/C cross-references with CLI.md in the doc matrix. Optional: generate read-only manifest for frontend (if unified completion is needed). |
9. Summary
- The "table" in the Gateway should primarily host Category A (channel control) SSOT, not all product slash commands.
- Category B stays client-side; Category C uses documentation and fields for name alignment — centralized execution logic is unnecessary.
- Success criterion: changing a command set in one place no longer causes divergence in pipelines and Gateway main paths; the CLI/IM experience boundary remains clear and documentable.
10. Current Command Status (based on gateway/slash_command.py)
The current command list has been split into a separate document: SlashCommands.md.