Skip to content

Commit 9da08de

Browse files
committed
Streaming
1 parent 2741fab commit 9da08de

File tree

2 files changed

+20
-31
lines changed

2 files changed

+20
-31
lines changed

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/thinking-block.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,11 @@ export function ThinkingBlock({
189189
isExpanded ? 'mt-1 max-h-[200px] opacity-100' : 'max-h-0 opacity-0'
190190
)}
191191
>
192-
<div className='whitespace-pre-wrap font-[470] font-season text-[12px] text-[var(--text-muted)] leading-none [&_*]:!text-[var(--text-muted)] [&_*]:!text-[12px] [&_*]:!leading-none [&_*]:!m-0 [&_*]:!p-0 [&_*]:!mb-0 [&_*]:!mt-0 [&_p]:!m-0 [&_h1]:!text-[12px] [&_h1]:!font-semibold [&_h2]:!text-[12px] [&_h2]:!font-semibold [&_h3]:!text-[12px] [&_h3]:!font-semibold [&_code]:!text-[11px] [&_ul]:!pl-4 [&_ul]:!my-0 [&_ol]:!pl-4 [&_ol]:!my-0 [&_li]:!my-0 [&_li]:!py-0 [&_br]:!leading-[0.5]'>
193-
<CopilotMarkdownRenderer content={content} />
192+
{/* Use simple pre tag during streaming for smooth performance */}
193+
<pre className='whitespace-pre-wrap font-[470] font-season text-[12px] text-[var(--text-muted)] leading-[1.15rem]'>
194+
{content}
194195
<span className='ml-1 inline-block h-2 w-1 animate-pulse bg-[var(--text-muted)]' />
195-
</div>
196+
</pre>
196197
</div>
197198
</div>
198199
)
@@ -228,6 +229,7 @@ export function ThinkingBlock({
228229
isExpanded ? 'mt-1 max-h-[200px] opacity-100' : 'max-h-0 opacity-0'
229230
)}
230231
>
232+
{/* Use markdown renderer for completed content */}
231233
<div className='whitespace-pre-wrap font-[470] font-season text-[12px] text-[var(--text-muted)] leading-none [&_*]:!text-[var(--text-muted)] [&_*]:!text-[12px] [&_*]:!leading-none [&_*]:!m-0 [&_*]:!p-0 [&_*]:!mb-0 [&_*]:!mt-0 [&_p]:!m-0 [&_h1]:!text-[12px] [&_h1]:!font-semibold [&_h2]:!text-[12px] [&_h2]:!font-semibold [&_h3]:!text-[12px] [&_h3]:!font-semibold [&_code]:!text-[11px] [&_ul]:!pl-4 [&_ul]:!my-0 [&_ol]:!pl-4 [&_ol]:!my-0 [&_li]:!my-0 [&_li]:!py-0 [&_br]:!leading-[0.5]'>
232234
<CopilotMarkdownRenderer content={content} />
233235
</div>

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/copilot-message.tsx

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -151,28 +151,13 @@ const CopilotMessage: FC<CopilotMessageProps> = memo(
151151
}, [message.content])
152152

153153
// Parse special tags from message content (options, plan)
154-
// During streaming, also check content blocks since message.content may not be updated yet
154+
// Only parse after streaming is complete to avoid affecting streaming smoothness
155155
const parsedTags = useMemo(() => {
156-
if (isUser) return null
157-
158-
// Try message.content first
159-
if (message.content) {
160-
const parsed = parseSpecialTags(message.content)
161-
if (parsed.options) return parsed
162-
}
163-
164-
// During streaming, check content blocks for options
165-
if (message.contentBlocks && message.contentBlocks.length > 0) {
166-
for (const block of message.contentBlocks) {
167-
if (block.type === 'text' && block.content) {
168-
const parsed = parseSpecialTags(block.content)
169-
if (parsed.options) return parsed
170-
}
171-
}
172-
}
156+
if (isUser || isStreaming) return null
173157

158+
// Only parse when not streaming - options should appear after message completes
174159
return message.content ? parseSpecialTags(message.content) : null
175-
}, [message.content, message.contentBlocks, isUser])
160+
}, [message.content, isUser, isStreaming])
176161

177162
// Get sendMessage from store for continuation actions
178163
const sendMessage = useCopilotStore((s) => s.sendMessage)
@@ -196,12 +181,14 @@ const CopilotMessage: FC<CopilotMessageProps> = memo(
196181
if (block.type === 'text') {
197182
const isLastTextBlock =
198183
index === message.contentBlocks!.length - 1 && block.type === 'text'
199-
// Clean content for this text block - strip special tags and excessive newlines
200-
const parsed = parseSpecialTags(block.content)
201-
const cleanBlockContent = parsed.cleanContent.replace(/\n{3,}/g, '\n\n')
184+
// During streaming, use raw content for smooth performance
185+
// Only strip special tags after streaming completes
186+
const cleanBlockContent = isStreaming
187+
? block.content.replace(/\n{3,}/g, '\n\n')
188+
: parseSpecialTags(block.content).cleanContent.replace(/\n{3,}/g, '\n\n')
202189

203-
// Skip if no content after stripping tags
204-
if (!cleanBlockContent.trim()) return null
190+
// Skip if no content after stripping tags (only when not streaming)
191+
if (!isStreaming && !cleanBlockContent.trim()) return null
205192

206193
// Use smooth streaming for the last text block if we're streaming
207194
const shouldUseSmoothing = isStreaming && isLastTextBlock
@@ -508,14 +495,14 @@ const CopilotMessage: FC<CopilotMessageProps> = memo(
508495
</div>
509496
)}
510497

511-
{/* Options selector when agent presents choices - streams in but disabled until complete */}
512-
{parsedTags?.options && Object.keys(parsedTags.options).length > 0 && (
498+
{/* Options selector when agent presents choices - only shown after streaming completes */}
499+
{!isStreaming && parsedTags?.options && Object.keys(parsedTags.options).length > 0 && (
513500
<OptionsSelector
514501
options={parsedTags.options}
515502
onSelect={handleOptionSelect}
516503
disabled={isSendingMessage}
517-
enableKeyboardNav={isLastMessage && parsedTags.optionsComplete === true}
518-
streaming={!parsedTags.optionsComplete}
504+
enableKeyboardNav={isLastMessage}
505+
streaming={false}
519506
/>
520507
)}
521508
</div>

0 commit comments

Comments
 (0)