Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

* An empty `input_date()` value no longer crashes Shiny. (#1528)

* `ui.Chat()` now works as expected inside Shiny modules. (#1582)

* Fixed bug where calling `.update_filter(None)` on a data frame renderer did not visually reset non-numeric column filters. (It did reset the column's filtering, just not the label). Now it resets filter's label. (#1557)

* Require shinyswatch >= 0.7.0 and updated examples accordingly. (#1558)
Expand Down
8 changes: 5 additions & 3 deletions shiny/ui/_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

from .. import _utils, reactive
from .._docstring import add_example
from .._namespaces import resolve_id
from .._namespaces import ResolvedId, resolve_id
from ..session import require_active_session, session_context
from ..types import MISSING, MISSING_TYPE, NotifyException
from ..ui.css import CssUnit, as_css_unit
Expand Down Expand Up @@ -147,9 +147,11 @@ def __init__(
on_error: Literal["auto", "actual", "sanitize", "unhandled"] = "auto",
tokenizer: TokenEncoding | MISSING_TYPE | None = MISSING,
):
if not isinstance(id, str):
raise TypeError("`id` must be a string.")

self.id = id
self.user_input_id = f"{id}_user_input"
self.id = resolve_id(id)
self.user_input_id = ResolvedId(f"{self.id}_user_input")
self._transform_user: TransformUserInputAsync | None = None
self._transform_assistant: TransformAssistantResponseChunkAsync | None = None
if isinstance(tokenizer, MISSING_TYPE):
Expand Down
32 changes: 32 additions & 0 deletions tests/playwright/shiny/components/chat/module/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from htmltools import Tag

from shiny import App, Inputs, Outputs, Session, module, ui


@module.ui
def chat_mod_ui() -> Tag:
return ui.chat_ui(id="chat")


@module.server
def chat_mod_server(input: Inputs, output: Outputs, session: Session):
chat = ui.Chat(id="chat")

@chat.on_user_submit
async def _():
user = chat.user_input()
await chat.append_message(f"You said: {user}")


app_ui = ui.page_fillable(
ui.panel_title("Hello Shiny Chat"),
chat_mod_ui("foo"),
fillable_mobile=True,
)


def server(input: Inputs, output: Outputs, session: Session):
chat_mod_server("foo")


app = App(app_ui, server)
18 changes: 18 additions & 0 deletions tests/playwright/shiny/components/chat/module/test_chat_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from playwright.sync_api import Page, expect
from utils.deploy_utils import skip_on_webkit

from shiny.playwright import controller
from shiny.run import ShinyAppProc


@skip_on_webkit
def test_validate_chat_append_user_message(page: Page, local_app: ShinyAppProc) -> None:
page.goto(local_app.url)

chat = controller.Chat(page, "foo-chat")

# Verify starting state
expect(chat.loc).to_be_visible(timeout=30 * 1000)
chat.set_user_input("A user message")
chat.send_user_input()
chat.expect_latest_message("You said: A user message", timeout=30 * 1000)