% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/chat_app.R
\name{chat_app}
\alias{chat_app}
\alias{chat_mod_ui}
\alias{chat_mod_server}
\title{Open a live chat application in the browser}
\usage{
chat_app(client, ..., bookmark_store = "url")

chat_mod_ui(id, ..., client = deprecated(), messages = NULL)

chat_mod_server(
  id,
  client,
  greeting = NULL,
  bookmark_on_input = TRUE,
  bookmark_on_response = TRUE
)
}
\arguments{
\item{client}{A chat object created by \pkg{ellmer}, e.g.
\code{\link[ellmer:chat_openai]{ellmer::chat_openai()}} and friends. This argument is deprecated in
\code{chat_mod_ui()} because the client state is now managed by
\code{chat_mod_server()}.}

\item{...}{In \code{chat_app()}, additional arguments are passed to
\code{\link[shiny:shinyApp]{shiny::shinyApp()}}. In \code{chat_mod_ui()}, additional arguments are passed to
\code{\link[=chat_ui]{chat_ui()}}.}

\item{bookmark_store}{The bookmarking store to use for the app. Passed to
\code{enable_bookmarking} in \code{\link[shiny:shinyApp]{shiny::shinyApp()}}. Defaults to \code{"url"}, which
uses the URL to store the chat state. URL-based bookmarking is limited in
size; use \code{"server"} to store the state on the server side without size
limitations; or disable bookmarking by setting this to \code{"disable"}.}

\item{id}{The chat module ID.}

\item{messages}{Initial messages shown in the chat, used only when \code{client}
(in \code{chat_mod_ui()}) doesn't already contain turns. Passed to \code{messages}
in \code{\link[=chat_ui]{chat_ui()}}.}

\item{greeting}{Optional greeting to set when the module initializes.
Accepts a static value (string, \code{\link[htmltools:HTML]{htmltools::HTML()}}, \code{\link[htmltools:tagList]{htmltools::tagList()}},
or \code{\link[=chat_greeting]{chat_greeting()}}) or a \strong{function} that generates the greeting
dynamically. See the \strong{Greeting} section below for details.}

\item{bookmark_on_input}{A logical value determines if the bookmark should be updated when the user submits a message. Default is \code{TRUE}.}

\item{bookmark_on_response}{A logical value determines if the bookmark should be updated when the response stream completes. Default is \code{TRUE}.}
}
\value{
\itemize{
\item \code{chat_app()} returns a \code{\link[shiny:shinyApp]{shiny::shinyApp()}} object.
\item \code{chat_mod_ui()} returns the UI for a shinychat module.
\item \code{chat_mod_server()} includes the shinychat module server logic, and
returns an environment containing:
\itemize{
\item \code{last_input}: A reactive value containing the last user input.
\item \code{last_turn}: A reactive value containing the last assistant turn.
\item \code{update_user_input()}: A function to update the chat input or submit a
new user input. Takes the same arguments as \code{\link[=update_chat_user_input]{update_chat_user_input()}},
except for \code{id} and \code{session}, which are supplied automatically.
\item \code{append()}: A function to append a new message to the chat UI. Takes
the same arguments as \code{\link[=chat_append]{chat_append()}}, except for \code{id} and \code{session},
which are supplied automatically.
\item \code{clear()}: A function to clear the chat history and the chat UI.
\code{clear()} takes an optional list of \code{messages} used to initialize the
chat after clearing. \code{messages} should be a list of messages, where
each message is a list with \code{role} and \code{content} fields. The
\code{client_history} argument controls how the chat client's history is
updated after clearing. It can be one of: \code{"clear"} the chat history;
\code{"set"} the chat history to \code{messages}; \code{"append"} \code{messages} to the
existing chat history; or \code{"keep"} the existing chat history.
\item \code{set_greeting()}: A function to set, stream, or clear the chat
greeting. Pass a \code{\link[=chat_greeting]{chat_greeting()}} object, a plain string, or
\code{NULL} to clear. Streaming greetings run inside an
\link[shiny:ExtendedTask]{shiny::ExtendedTask} so the session stays responsive; if called
while a greeting is already streaming, the new greeting is queued.
If the greeting has already been dismissed, calling \code{set_greeting()}
updates the content but does not make it visible again; call
\code{clear(greeting = TRUE)} first to show a new greeting after dismissal.
\item \code{status}: A reactive value indicating the current chat interaction
state. Returns \code{"idle"} when no response is in progress, or
\code{"streaming"} while a response is actively being received.
\item \code{client}: The current chat client object (an active binding that
always reflects the latest client, even after \code{set_client()}
is called).
\item \code{set_client(new_client, sync = TRUE)}: Replace the chat client used by
the module. When \code{sync} is \code{TRUE} (the default), the new client
inherits conversation turns, system prompt, and tools from the previous
client so the conversation continues seamlessly. Set \code{sync = FALSE} to
use the new client as-is. If a response is currently streaming, the
swap is deferred until the stream completes. If called multiple times
while streaming, only the most recent new client is used.
}
}
}
\description{
Create a simple Shiny app for live chatting using an \link[ellmer:Chat]{ellmer::Chat} object.
Note that these functions will mutate the input \code{client} object as
you chat because your turns will be appended to the history.

The app created by \code{chat_app()} is suitable for interactive use by a single
user. For multi-user Shiny apps, use the Shiny module chat functions --
\code{chat_mod_ui()} and \code{chat_mod_server()} -- and be sure to create a new chat
client for each user session.
}
\section{Functions}{
\itemize{
\item \code{chat_app()}: A simple Shiny app for live chatting. Note that this
app is suitable for interactive use by a single user; do not use
\code{chat_app()} in a multi-user Shiny app context.

\item \code{chat_mod_ui()}: A simple chat app module UI.

\item \code{chat_mod_server()}: A simple chat app module server.

}}
\section{Greeting}{


When \code{greeting} is a \strong{function}, the module calls it each time the
\code{greeting_requested} event fires — on first view when the chat is empty,
and again after \code{clear(greeting = TRUE)}. The function should return a
\code{\link[=chat_greeting]{chat_greeting()}} (typically wrapping a stream). Static values (strings,
\code{\link[=chat_greeting]{chat_greeting()}} objects) are set once at init and do not regenerate.

The module detects \strong{named arguments} in the greeting function to decide
what to pass. Currently the only recognized argument is \code{client}.

\strong{\verb{function(client)}} (recommended). The module clones the \code{client}
passed to \code{chat_mod_server()}, wipes its turn history, and passes the
fresh clone as \code{client}. This avoids manually creating and configuring
a separate client:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{chat_mod_server("chat", client, greeting = function(client) \{
  stream <- client$stream_async("Generate a short welcome message.")
  chat_greeting(stream)
\})
}\if{html}{\out{</div>}}

\strong{\verb{function()}} (zero arguments). You create and manage your own client:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{chat_mod_server("chat", client, greeting = function() \{
  greeter <- ellmer::chat_openai(model = "gpt-4o")
  stream <- greeter$stream_async("Generate a short welcome message.")
  chat_greeting(stream)
\})
}\if{html}{\out{</div>}}

\strong{Static value.} Set once; does not regenerate after \code{clear()}:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{chat_mod_server("chat", client, greeting = "## Welcome!\\n\\nHow can I help?")
}\if{html}{\out{</div>}}

The returned \code{set_greeting()} helper is available for cases where you need
to set a greeting outside the greeting lifecycle.
}

\examples{
\dontrun{
# Interactive in the console ----
client <- ellmer::chat_anthropic()
chat_app(client)

# Inside a Shiny app ----
library(shiny)
library(bslib)
library(shinychat)

ui <- page_fillable(
  titlePanel("shinychat example"),

  layout_columns(
    card(
      card_header("Chat with Claude"),
      chat_mod_ui(
        "claude",
        messages = list(
          "Hi! Use this chat interface to chat with Anthropic's `claude-3-5-sonnet`."
        )
      )
    ),
    card(
      card_header("Chat with ChatGPT"),
      chat_mod_ui(
        "openai",
        messages = list(
          "Hi! Use this chat interface to chat with OpenAI's `gpt-4o`."
        )
      )
    )
  )
)

server <- function(input, output, session) {
  claude <- ellmer::chat_anthropic(model = "claude-3-5-sonnet-latest") # Requires ANTHROPIC_API_KEY
  openai <- ellmer::chat_openai(model = "gpt-4o") # Requires OPENAI_API_KEY

  chat_mod_server("claude", claude)
  chat_mod_server("openai", openai)
}

shinyApp(ui, server)
}

}
