posit-dev / posit-dev/shinychat
R pkg: argument to control how errors are displayed in the chat
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 139
- Forks
- 28
- Avg merge
- 23h 44m
- Merged PRs (30d)
- 50
Description
When an error occurs while streaming an assistant response (e.g. inside chat$stream_async()), chat_append_stream() catches it and appends (via chat_append_message()) sanitized_chat_error(reason) into the chat UI as a normal chat bubble.
sanitized_chat_error() lives in pkg-r/R/utils.R, along with further helpers:
needs_sanitized <- function(err) {
isTRUE(getOption("shiny.sanitize.errors")) &&
!inherits(err, "shiny.custom.error")
}
sanitized_error_message <- function(err) {
if (needs_sanitized(err)) {
"An error occurred. Please try again or contact the app author."
} else {
strip_ansi(conditionMessage(err))
}
}
notify_error <- function(prefix, err) {
shiny::showNotification(
paste0(prefix, ": ", sanitized_error_message(err)),
type = "error",
duration = NULL
)
rlang::warn(prefix, parent = err)
}
sanitized_chat_error <- function(err) {
if (needs_sanitized(err)) {
sprintf("\n\n**%s**", sanitized_error_message(err))
} else {
sprintf(
"\n\n**An error occurred:**\n\n```\n%s\n```",
sanitized_error_message(err)
)
}
}
As we see, if shiny.sanitize.errors is explicitly set to TRUE, the chat shows the generic message. Otherwise, the chat bubble will show: **An error occurred:** followed by the raw conditionMessage(). A conditionMessage() text is whatever it is—it may be satisfactory, but chances are that it is not helpful, reveals confidential information, ...
shiny.sanitize.errors is a global option. If an app developer wants to scope it to a single shinychat function, or to otherwise take ownership of a specific error message shown by shinychat, things get complicated. Not because of a flaw in the implementation—shiny.sanitize.errors being read asynchronously, inside chat_append_stream()'s own promises::catch() handler, is absolutely fine as is.
Proposal
Add an argument to the following functions, that allows app authors to define how the error is displayed in the chat:
chat_append()(passing on tochat_append_stream())chat_server()(passing on tochat_append()three times: https://github.com/posit-dev/shinychat/blob/e74ed266016038667a78ae8d1bf6a81089bb548f/pkg-r/R/chat_app.R#L323, https://github.com/posit-dev/shinychat/blob/e74ed266016038667a78ae8d1bf6a81089bb548f/pkg-r/R/chat_app.R#L486, https://github.com/posit-dev/shinychat/blob/e74ed266016038667a78ae8d1bf6a81089bb548f/pkg-r/R/chat_app.R#L688)chat_app()(passing on tochat_server())
I haven't thought about the name of the argument yet, and I'm open to what values the argument should take. Here are some initial notes:
- Argument name
error_message, ... .on_errorwould likely be misleading in multiple ways. - Accepted values String? Function? Enum, mirroring Python:
"auto"("actual"or"sanitize"depending onshiny.sanitize.errors)/"actual"(e.g. what we now have ifshiny.sanitize.errorsis notTRUE) /"sanitize"(e.g. what we now have ifshiny.sanitize.errorsisTRUE) ("unhandled"may or may not make sense)? Or a combination of some of them?
Python package
shinychat's Python Chat class exposes an on_error parameter, set once per Chat instance. However, Python's enum options control whether/how a popup appears, while the R proposal is about what text appears in the chat itself.
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 pkg-r/R/chat.R, pkg-r/R/chat_app.R, and pkg-r/R/utils.R, focusing on chat_append_stream(), chat_append(), chat_server(), chat_app(), and sanitized_chat_error(). Trace how errors are currently formatted and propagated through the listed functions. Done means app authors can control the displayed error behavior through the new argument while existing shiny.sanitize.errors behavior remains supported.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- r
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100