Adopt shinychat 0.4.0 greeting API with bookmark persistence#249
Draft
gadenbuie wants to merge 8 commits into
Draft
Adopt shinychat 0.4.0 greeting API with bookmark persistence#249gadenbuie wants to merge 8 commits into
gadenbuie wants to merge 8 commits into
Conversation
Render a static greeting via chat_ui(greeting=) and generate a dynamic greeting on input$chat_greeting_requested via chat_set_greeting(), replacing the startup observer that appended the greeting as a message. Greetings are non-dismissible. Generated greetings stream from an isolated client (tools = NULL) so they stay out of the conversation history, and the has_greeted bookmark bookkeeping is removed.
Render a static greeting via chat_ui(greeting=) and generate a dynamic greeting on the greeting_requested input via Chat.set_greeting(), replacing the startup effect that appended the greeting as a message. Greetings are non-dismissible. Generated greetings stream from an isolated client (tools=None) so they stay out of the conversation history, and the has_greeted bookmark bookkeeping is removed.
shinychat bookmarking only saves the ellmer client's chat state, not the greeting set via chat_set_greeting(). Since generated greetings are produced on an isolated client, they are absent on reload. Capture the generated greeting text and save/restore it via the module's onBookmark/onRestore hooks, re-displaying it on restore and reusing it instead of regenerating when the greeting is requested again.
shinychat bookmarking only saves the chatlas client's chat state, not the greeting set via Chat.set_greeting(). Since generated greetings are produced on an isolated client, they are absent on reload. Capture the generated greeting text and save/restore it via the module's on_bookmark/on_restore hooks, re-displaying it on restore and reusing it instead of regenerating when the greeting is requested again.
The generated-greeting bookmark/restore plumbing exists only because shinychat does not persist or expose greeting state. Point the workaround sites at posit-dev/shinychat#253 and spell out what to remove if it is fixed.
On empty-chat bookmark restore both the greeting_requested guard and onRestore set the greeting (harmless, identical content); on non-empty restore greeting_requested never fires, so onRestore is the only path. Document this at the guard branch in both packages.
The greeting now renders in shinychat's dedicated greeting slot (.shiny-chat-greeting) rather than as a persistent message in .shiny-chat-messages-content. Point the e2e greeting assertions and viz setup fixtures at the greeting slot instead of loc_messages / loc_latest_message.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Migrates greeting handling in both the R and Python packages onto the first-class greeting API in shinychat (which both packages already require at
>= 0.4.0), replacing the old "append the greeting as a permanent assistant message on startup" pattern.chat_ui(greeting=)/chat_greeting()— shown instantly on load with no server round-trip, and they persist across bookmark/restore for free because they're part of the UI definition.greetingis provided) now use the{id}_greeting_requestedinput +chat_set_greeting()/Chat.set_greeting(), instead of an always-running startup observer/effect. They're generated on an isolated client (client(tools = NULL)/client(tools=None)) soGREETING_PROMPTand its response stay out of the live conversation's model history. The existing "no greeting provided" warning is preserved.has_greetedbookkeeping (reactive value + its bookmark save/restore). shinychat now owns greeting visibility and dismissal state.dismissible = FALSEso the welcome + suggestion cards remain visible after the conversation starts (closest to the prior permanent-message behavior).Bookmark-restore workaround (shinychat#253)
shinychat's bookmarking only round-trips the ellmer/chatlas client's chat turns; a greeting set via
chat_set_greeting()is neither a turn nor exposed as readable state, so generated greetings are lost on restore. Until posit-dev/shinychat#253 is fixed, this PR captures the generated greeting text (from the isolated client's last turn) and saves/restores it through the module's ownonBookmark/onRestorehooks. Thegreeting_requestedhandler reuses a restored greeting instead of regenerating. Static greetings need no tracking. Source comments at each site point back to #253 with removal hints for when it lands.Verification
Static greeting (persists for free):
The greeting renders immediately on load (no LLM call). Bookmark the app and reopen the URL — the greeting is still there.
Generated greeting (captured + restored via the workaround):
A warning is emitted and a greeting is generated once. Send a message, bookmark, then reopen the bookmark URL: the same generated greeting is restored above the conversation rather than disappearing or being regenerated.
Python mirrors both behaviors (
QueryChat(...).app()/from_*constructors).