posit-dev / posit-dev/shinychat
Feature: standalone register_slash_command() for chat_ui() without chat_server()
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 139
- Forks
- 28
- Avg merge
- 23h 44m
- Merged PRs (30d)
- 50
Description
Summary
chat_app.R has a standing TODO to "Support a standalone register_slash_command() that works outside the returned environment (e.g., so callers don't have to thread the return value)." This proposes exactly that.
Motivation
Slash commands are currently only reachable through chat_server()'s $slash_command() method. That has two friction points:
- You must thread the returned object around. To register a command from anywhere other than right next to the
chat_server()call, you have to capture and pass its return value. - Fully custom chat loops can't use slash commands at all. The Get started vignette says as much: "Slash commands are currently available only through
chat_server(), not when building a fully custom chat loop withchat_ui()andchat_append()directly." Apps that drivechat_ui()with their own server logic (custom streaming, an external agent loop) can't offer the official palette.
Proposal
Export a free function that mirrors $slash_command() but is callable anywhere with just the chat id and session:
register_slash_command(
id, name, description, handler, ...,
echo = NULL, force = FALSE,
session = getDefaultReactiveDomain()
)
- Same
handlersemantics as$slash_command()(0/1-arg, orNULLfor client-side handling viashiny:chat-slash-command); a 1-arg handler receives aContentSlashCommand. - The command registry lives in
session$userDatakeyed by the namespacedid(the same idiom already used for bookmark info inchat_restore.R), and the dispatch + sync observers are set up once, lazily — so no return value needs threading. - The slash machinery is factored into an internal helper that
chat_server()reuses, so both paths share a single implementation and can't drift.
Follows shinychat's argument conventions (id first, session last, matching chat_append() / chat_clear() / update_chat_user_input()).
Open question
R's $slash_command() returns an unregister closure; I've kept that for register_slash_command(). Would you prefer a separate remove_slash_command(id, name, session) for parity with the Python Chat.remove_slash_command() method, or is returning the unregister function the right R idiom here? Happy to adjust.
I have a draft PR ready that implements this as a pure refactor (no behavior change to chat_server()), with standalone tests and a clean R CMD check.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the TODO in chat_app.R and the existing $slash_command() implementation used by chat_server(); inspect chat_restore.R for the session$userData registry pattern. Review the standalone tests mentioned in the proposal and run R CMD check. Done means standalone registration works with chat_ui() and chat_append(), chat_server() continues to behave unchanged, and unregistering remains defined.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- r
- Domain
- full-stack
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100