fix(web): stamp focused-app context on main-composer messages#382
Open
mgoldsborough wants to merge 1 commit into
Open
fix(web): stamp focused-app context on main-composer messages#382mgoldsborough wants to merge 1 commit into
mgoldsborough wants to merge 1 commit into
Conversation
Messages typed into the global chat panel (ChatChrome) were sent with no appContext. Only the in-app "ask about this" channel (AppWithChat.handleChat) stamped it, so a user typing into the side panel while viewing an app got an agent that couldn't see which app — or which document — they were looking at. The backend gates its entire focused-app resolution on request.appContext (runtime.ts), so no appContext means no "currently viewing" section and no injected app visible state, even though the app (e.g. collateral) publishes it via useVisibleState. Add a small FocusedAppContext: the active AppWithChat publishes its AppContext while mounted (and clears it on unmount / route change); ChatChrome reads it and stamps it on outgoing messages. useChat already enriches appContext with the app's latest visible state from the bridge store, so the open-document pointer now reaches the agent. Standalone context (not folded into ShellContext) so focus changes re-render only the panel and the app view, not every shell consumer. Non-app routes publish null → no appContext, unchanged behavior.
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.
Problem
A user viewing an app (e.g. collateral) and typing into the main chat panel got an agent that couldn't see what they were looking at — it would say things like "I can't read your UI state directly — collateral doesn't expose a 'currently viewing' pointer."
The bundle is innocent: collateral does publish its current view via
useVisibleState(activeDocument {id,name}+ a summary). The break is in the web shell.Root cause
The globally-mounted chat panel
ChatChromesent messages with noappContext:The only path that stamped app context was
AppWithChat.handleChat— the in-app "ask about this" channel — which fires only when the iframe itself initiates a send, not when you type into the side panel.The backend confirms the consequence:
runtime.tsgates its entire focused-app resolution onif (request.appContext)and does not derive the focused app fromX-Workspace-Id. So noappContext→ no focused app → no "user is currently viewing X" section and no injected app visible state. Exactly the symptom.Fix
A small standalone
FocusedAppContext:AppWithChatpublishes itsAppContextwhile mounted and clears it on unmount / route change.ChatChromereads it and stamps it on outgoing messages.useChatalready enrichesappContextwith the app's latest visible state from the bridge store, so the open-document pointer now reaches the agent.Standalone context (not folded into
ShellContext) so focus changes re-render only the two participants, not every shell consumer. Non-app routes publishnull→ noappContext, unchanged behavior. The in-app channel and its[App Context: …]text prefix are untouched.Test
web/test/FocusedAppContext.test.tsxpins the publish→read contract across two components (the exact link that was broken), the inert out-of-provider default, and clear-on-null.Verification
bun run verify:static— passbun run test:web— 462 pass / 0 failcd web && bun run build— clean(The unrelated
test:unitdompurifyfailure is a missing nested dependency insrc/bundles/automations/ui/, present on a fresh checkout regardless of this change.)