From 8719d5bf6f92c4f54275454cef848fe38812cd1f Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Mon, 18 Aug 2025 11:19:25 -0400 Subject: [PATCH 1/2] feat(pkg-r): Stream from chat in ExtendedTask --- pkg-r/DESCRIPTION | 1 + pkg-r/R/querychat.R | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/pkg-r/DESCRIPTION b/pkg-r/DESCRIPTION index f5471586..3d39b3e6 100644 --- a/pkg-r/DESCRIPTION +++ b/pkg-r/DESCRIPTION @@ -21,6 +21,7 @@ Imports: ellmer (>= 0.3.0), htmltools, lifecycle, + promises, purrr, rlang, shiny, diff --git a/pkg-r/R/querychat.R b/pkg-r/R/querychat.R index cae09e7a..f90327a1 100644 --- a/pkg-r/R/querychat.R +++ b/pkg-r/R/querychat.R @@ -285,13 +285,22 @@ querychat_server <- function(id, querychat_config) { ) } - # Handle user input + append_stream_task <- shiny::ExtendedTask$new( + function(client, user_input) { + stream <- client$stream_async( + user_input, + stream = "content" + ) + + p <- promises::promise_resolve(stream) + promises::then(p, function(stream) { + shinychat::chat_append("chat", stream) + }) + } + ) + shiny::observeEvent(input$chat_user_input, { - # Add user message to the chat history - shinychat::chat_append( - "chat", - chat$stream_async(input$chat_user_input, stream = "content") - ) + append_stream_task$invoke(chat, input$chat_user_input) }) list( From a04751d61cd75f92785b4277f3d58b3ef56c4b37 Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Mon, 18 Aug 2025 11:21:41 -0400 Subject: [PATCH 2/2] docs: Add NEWS item --- pkg-r/NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg-r/NEWS.md b/pkg-r/NEWS.md index d44c08d2..ccf7dbda 100644 --- a/pkg-r/NEWS.md +++ b/pkg-r/NEWS.md @@ -17,3 +17,5 @@ * the `querychat.client` R option, which can be any of the above options, * the `QUERYCHAT_CLIENT` environment variable, which should be a provider-model string, * or the default model from `ellmer::chat_openai()`. + +* `querychat_server()` now uses a `shiny::ExtendedTask` for streaming the chat response, which allows the dashboard to update and remain responsive while the chat response is streaming in. (#63)