Repository navigation
Conversation
…sign-in AIConversation lays an agent conversation out by turn. parseMessageParts reads a reply's ai_reasoning and ai_tool_call attachments, shown by AIReasoning and AIToolCall, with AIToolApproval for a tool that asks first and AIToolAuthorization for a connector sign-in, run in a popup by createPopupAuthorizer and finished by completeConnectorSignIn. Also AISuggestions, AIReplyActions, AIMessageComposer.ChatOptions, default attachment previews and a className merge on the composer. Mirrors StreamChatAI on iOS and stream-chat-android-ai-compose.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
|
Size Change: +70 kB (+5.92%) 🔍 Total Size: 1.25 MB 📦 View Changed
ℹ️ View Unchanged
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## release-v14 #3376 +/- ##
===============================================
- Coverage 86.84% 86.73% -0.12%
===============================================
Files 526 563 +37
Lines 16699 18757 +2058
Branches 5251 5897 +646
===============================================
+ Hits 14503 16268 +1765
- Misses 2196 2489 +293 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- Sanitise attachment links and images, keeping blob and image data URLs. - Keep waiting for a sign-in while a provider page severs the popup. - Retry loading older messages after a failure or an empty page. - Measure turns only when they change, and on scroll once a frame. - Drop the entry memo, so a new rating shows with unchanged messages. - Write the thinking clock only from effects. - Build ChatOptions on the SDK's Dropdown, and sizes on prettifyFileSize. - Keep one preview URL per picked image.
An agent's answer had no message styling of its own: lists fell back to the browser's 40px indent, headings, links and quotes were unstyled, paragraphs sat 8px apart at the chat's 20px line height, and a 12px inset pushed the text off the edge of the steps above it. The answer is now set in the SCR scale, without a bubble: 16/24 body, headings a step up with more room above than below, 12px between blocks, lists, links, quotes, rules, inline code and tables styled on SCR tokens, and the text starts at the steps' edge. The steps, reasoning, cards and typing indicator move from 15/13px to the scale's 14/12px. `ai-scale()` reads the SCR spacing, type and radius tokens with literal fallbacks, as `ai-token()` does for colours. Code text, punctuation and comments follow the SCR text colours, so they read in dark mode.
StreamingMessage typed two letters every 30ms, about 67 a second, however fast the answer arrived, so a 1,500-character reply delivered in 3 s took 22 s to finish on screen. By default it now sets its pace as text arrives: enough letters a frame to write what is behind within 400ms, and at least one, so a long chunk appears almost at once and a trickle types as it comes. Text there from the start still shows at once. letterIntervalMs and renderingLetterCount still give a fixed pace, and the core useMessageTextStreaming hook is unchanged.
TextInput was an <input type="text">, which holds no newline. It is a textarea now that grows with its lines up to 200px and then scrolls, re-fitted when its width changes. Enter sends, Shift+Enter starts a new line, and Enter while an input method is composing does neither. TextInput's props are a textarea's.
🎯 Goal
Stream Agents replies carry more than text: the model's reasoning, each tool call, a question before a tool runs, and a sign-in card when the agent reaches for an account the user hasn't connected. StreamChatAI on iOS and
stream-chat-android-ai-composeon Android render all of it. This bringsstream-chat-react/ai-componentsto the same place, so a web assistant (Juno, the personal-assistant example in Vision-Agents) has the same building blocks.🛠 Implementation details
parseMessageParts,AIReasoningPart,AIToolCallPart,isAwaitingApproval(userId, clientId),isAwaitingAuthorization(userId)AIMessagePart,AIToolCallPartAIToolApprovercontext,AIClientIdentity.installId(),AIToolApprovalinline andAIToolApprovalCardstandaloneAIToolApprover,AIToolApprovalViewcreatePopupAuthorizer({ returnUrl, decline }),completeConnectorSignIn(),AIToolAuthorization/AIToolAuthorizationCardAIWebAuthentication,AIToolAuthorizationViewAIConversation,fromStreamMessage,AIUserMessage,AIAssistantMessage,AIMessageAttachment,AITypingIndicatorAIConversationViewAIReasoning("Thinking... 7s", then "Thought for 12s"),AISuggestions,AIReplyActions,AIMessageComposer.ChatOptionsAIReasoningView,ChatOptionsListThe popup sign-in follows the router's web protocol. The page opens the router's sign-in URL on the click, waits for
va.connector.oauth.ready, and then postsva.connector.oauth.handoffwith the token. The provider sends the popup back to the app'sreturnUrl. That page runscompleteConnectorSignIn(), which reports the result over aBroadcastChannel, since the launch page clearswindow.opener.The agent's answer (
StreamingMessage) is set in the SCR scale, without a bubble: 16/24 body, headings a step up, 12px between blocks, lists, links, quotes, rules, inline code and tables on SCR tokens, starting at the steps' edge. The steps, reasoning and cards move from 15/13px to the scale's 14/12px.ai-scale()reads the SCR spacing, type and radius tokens with literal fallbacks, besideai-token()for colours.Smaller fixes along the way:
AIMessageComposermerges a passedclassNameinstead of replacing its own.AIMessageComposer.AttachmentPreviewshows default previews when it has no children.StreamingMessageno longer adds a 12px inset of its own.New strings in all 12 locales, styles on the existing tokens (light and dark), and a README section.
Tests:
messageParts.test.ts,popupAuthorizer.test.ts(with a mockedwindow.open, postMessage and BroadcastChannel),AIMessagePartViews.test.tsx,AIConversation.test.tsx, plus additions to the composer, attachment preview and SSR tests.yarn typesandvitest run src/plugins/AIComponents(271 tests) pass.Not done:
yarn types:testsfails across the repo today, and two of its errors are in new test files (AIConversation.test.tsx:283, an attachment literal with anidthatAttachmentdoesn't declare, andrenderWithEnglish.tsx:23,childrentyped asReactElement). CI doesn't run it.Used by
examples/voice_agents/react_assistantin Vision-Agents (GetStream/Vision-Agents,examples/react-assistant), which runs against a packed build of this branch until a 14.x release has it.🎨 UI Changes
Juno on the web, built on these components, was checked end to end against a local router: reasoning and tool steps, approvals and declines, the Linear sign-in card with Not now, photos, and Think harder. Screenshots to follow.