feat(chat-with-content): scope to the viewer, surface errors, harden startup - #447
Open
amylin1249 wants to merge 9 commits into
Open
feat(chat-with-content): scope to the viewer, surface errors, harden startup#447amylin1249 wants to merge 9 commits into
amylin1249 wants to merge 9 commits into
Conversation
This was referenced Jul 28, 2026
Contributor
Extension release summary😴 Changed but won't releaseThe following extensions have code changes but the manifest version hasn't been incremented:
If you intended to release these changes, update the See the contributing guide for details. |
amylin1249
force-pushed
the
cwc-02-app-rework
branch
6 times, most recently
from
July 29, 2026 15:33
9928535 to
900d730
Compare
amylin1249
marked this pull request as ready for review
July 29, 2026 17:40
Every user-visible error message (chat provider startup, content list/open, markdownify conversion, chat streaming) interpolated the raw exception text into the screen or a toast. A viewer can't act on SDK/vendor error detail, and some of these failures (bad LLM config, a broken provider) are only fixable by an administrator anyway. Log the raw cause with print() instead, and show a fixed, non-technical message that tells the viewer what to do next.
Exchanging the session token, reading the viewer's name, listing their content, and opening a selected item were all blocking Connect API calls made directly in server() or a plain reactive effect. Both run under Shiny's single, process-wide reactive lock, so a slow call in any of them stalled every other session on that worker, not just the caller's. Move the session/content-list resolution into one extended task (mirroring the existing markdownify-conversion fix), and wrap the remaining blocking call (opening a selected item) in asyncio.to_thread, so none of them run on the shared lock or event loop.
…currently Fetching the content list and reading the viewer's own name don't depend on each other, but ran as two sequential Connect API round trips. Run them concurrently instead, and match the explicit-underscore unpacking style used everywhere else resolve_session's result is read.
The posit-sdk sets no request timeout, so an unresponsive Connect server could hang a session-exchange, content-list, identity, or content-open call indefinitely. asyncio.to_thread can't interrupt a call already in flight, so this bounds how long the app waits (and reports the failure) rather than how long the abandoned thread runs, matching the existing timeout treatment for the Bedrock probe and chat streaming.
CONNECT_API_TIMEOUT_SECONDS (30s) bounded content.find() the same as the single-item lookups (session exchange, .me, content.get), but it's a paginated fetch of everything the viewer can see: on a large Connect instance it can legitimately take longer without anything being wrong. Give it its own longer CONTENT_LIST_TIMEOUT_SECONDS, use the shared SESSION_TIMEOUT_DETAIL message for the session-exchange timeout so its wording matches its two siblings, and fix CONNECT_API_TIMEOUT_SECONDS's comment to name all of its call sites.
Shiny's fillable page locks body to exactly the viewport height, so when
the setup screen's content is taller than one screen (e.g. both the LLM and
integration steps showing), body's own gradient background stopped at the
viewport edge, leaving a hard line and plain white below it on scroll.
Root cause (verified with a real browser, not guessed): body has 24px
padding from bslib's own CSS that our plain `body { padding: 0 }` can't
override (a class selector always beats a bare element selector), and
.setup-container isn't a Shiny "fill item," so it can grow taller than
body's fixed box. Body's background still covers the normal case (including
that padding); .setup-container's identical background, which already
grows to fit whatever content it holds, seamlessly extends past body's
edge for the overflow case. The 800px reading width moves to .setup-card
since .setup-container itself must stay full width for its background to
reach the sides of the viewport.
Use background-attachment: fixed instead of duplicating the gradient onto .setup-container. Fixed keeps the background painted relative to the viewport rather than the element's box, so it fills the visible window regardless of body's own height -- one property instead of restructuring which element owns the 800px width cap. Matches the pattern already used for the same case in simple-shiny-chat-with-mcp's setup screen.
The SDK sets no timeout on its session, so a Connect server that accepts a connection and then goes quiet hangs the calling thread forever. asyncio can stop waiting on those calls but cannot interrupt them, so in a Shiny worker the threads pile up and eventually starve it. A session adapter supplies a default read timeout through requests' own extension point, applied to the deploy client and to the viewer-scoped client the token exchange builds. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amylin1249
force-pushed
the
cwc-02-app-rework
branch
from
August 1, 2026 16:22
1c7b1d5 to
b10ea88
Compare
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.
Split out of #433 into small, reviewable PRs (tracking issue #429). Stacked 2/3 — stacked on #446, merge bottom-up.
Scopes the app to the signed-in viewer (visitor-scoped Connect client, setup screen when the session or integration is missing), surfaces errors instead of failing silently, hardens startup (bounded Bedrock probe and Connect API calls), and serializes all replies through one extended task so overlapping streams can't interleave or drop chunks.
The Connect API hardening has two layers, bounding different things:
CONNECT_API_TIMEOUT_SECONDS(30s) andCONTENT_LIST_TIMEOUT_SECONDS(120s) cap how long the app waits before reporting a failure.helpers.CONNECT_REQUEST_TIMEOUT_SECONDS(60s) is a read timeout on the SDK's own session, supplied through arequestsadapter. The SDK sets none, andasyncio.to_threadcan stop waiting on a stuck call but can't interrupt it, so without this a Connect server that goes quiet mid-response ties up a worker thread until the app restarts. Applied to the deploy client and to the viewer-scoped client the token exchange builds, since that one gets a fresh session. Verified against a socket server that accepts and then goes silent: raisesReadTimeoutat the deadline, where the unpatched session was still hanging.requestsis now a declared dependency, sincehelpers.pyimports it directly.