posit-dev / posit-dev/shinychat

R pkg: argument to control how errors are displayed in the chat

Open
#276 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

ai-triage:done Priority: Medium
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:

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_error would likely be misleading in multiple ways.
  • Accepted values String? Function? Enum, mirroring Python: "auto" ("actual" or "sanitize" depending on shiny.sanitize.errors)/"actual" (e.g. what we now have if shiny.sanitize.errors is not TRUE) / "sanitize" (e.g. what we now have if shiny.sanitize.errors is TRUE) ("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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.