Skip to content

Commit 94d32d9

Browse files
committed
fix(chat): limit copied content to orchestrator output
1 parent f511dde commit 94d32d9

5 files changed

Lines changed: 22 additions & 32 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export {
22
assistantMessageHasRenderableContent,
3-
getRenderableMessageText,
3+
getOrchestratorMessageText,
44
MessageContent,
55
} from './message-content'
66
export type { MessagePhase } from './utils'

apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content.test.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import type { ContentBlock } from '../../types'
2727
import {
2828
assistantMessageHasVisibleExecutingTool,
2929
deriveThinkingLabel,
30-
getRenderableMessageText,
30+
getOrchestratorMessageText,
3131
parseBlocks,
3232
shouldSmoothTextSegment,
3333
} from './message-content'
@@ -101,8 +101,8 @@ function toolEnvelope(
101101
} as PersistedStreamEventEnvelope
102102
}
103103

104-
describe('getRenderableMessageText', () => {
105-
it('omits span-based subagent text that has no visible agent group', () => {
104+
describe('getOrchestratorMessageText', () => {
105+
it('copies only orchestrator text from span-based messages', () => {
106106
const blocks: ContentBlock[] = [
107107
subagentStart('research', 'span-visible', 'main'),
108108
{
@@ -120,10 +120,10 @@ describe('getRenderableMessageText', () => {
120120
mainText('Main answer.'),
121121
]
122122

123-
expect(getRenderableMessageText(blocks, 'Fallback.')).toBe('Visible research. \n\nMain answer.')
123+
expect(getOrchestratorMessageText(blocks, 'Fallback.')).toBe('Main answer.')
124124
})
125125

126-
it('omits legacy subagent text that has no parent group', () => {
126+
it('copies only orchestrator text from legacy messages', () => {
127127
const blocks: ContentBlock[] = [
128128
{ type: 'subagent_text', content: 'Hidden orphan. ', timestamp: 1 },
129129
{
@@ -141,11 +141,12 @@ describe('getRenderableMessageText', () => {
141141
mainText('Main answer.'),
142142
]
143143

144-
expect(getRenderableMessageText(blocks, 'Fallback.')).toBe('Visible research. \n\nMain answer.')
144+
expect(getOrchestratorMessageText(blocks, 'Fallback.')).toBe('Main answer.')
145145
})
146146

147-
it('separates rendered blocks when streamed text has no boundary whitespace', () => {
147+
it('separates orchestrator text blocks around excluded subagent output', () => {
148148
const blocks: ContentBlock[] = [
149+
mainText('Starting answer.'),
149150
subagentStart('research', 'span-visible', 'main'),
150151
{
151152
type: 'subagent_text',
@@ -156,7 +157,7 @@ describe('getRenderableMessageText', () => {
156157
mainText('Main answer.'),
157158
]
158159

159-
expect(getRenderableMessageText(blocks, 'Fallback.')).toBe('Visible research.\n\nMain answer.')
160+
expect(getOrchestratorMessageText(blocks, 'Fallback.')).toBe('Starting answer.\n\nMain answer.')
160161
})
161162
})
162163

apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content.tsx

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -496,27 +496,16 @@ function joinRenderableText(parts: string[]): string {
496496
return parts.filter(Boolean).join('\n\n')
497497
}
498498

499-
function getAgentGroupText(items: AgentGroupItem[]): string {
500-
return joinRenderableText(
501-
items.map((item) => {
502-
if (item.type === 'text') return item.content
503-
if (item.type === 'agent_group') return getAgentGroupText(item.group.items)
504-
return ''
505-
})
506-
)
507-
}
508-
509-
/** Returns only the text represented by the same segment tree the transcript renders. */
510-
export function getRenderableMessageText(blocks: ContentBlock[], fallbackContent: string): string {
499+
/** Returns only top-level orchestrator text, excluding agent groups and other UI segments. */
500+
export function getOrchestratorMessageText(
501+
blocks: ContentBlock[],
502+
fallbackContent: string
503+
): string {
511504
const parsed = blocks.length > 0 ? parseBlocks(blocks) : []
512505
if (parsed.length === 0) return fallbackContent
513506

514507
return joinRenderableText(
515-
parsed.map((segment) => {
516-
if (segment.type === 'text') return segment.content
517-
if (segment.type === 'agent_group') return getAgentGroupText(segment.items)
518-
return ''
519-
})
508+
parsed.map((segment) => (segment.type === 'text' ? segment.content : ''))
520509
)
521510
}
522511

apps/sim/app/workspace/[workspaceId]/home/components/mothership-chat/copyable-markdown.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ vi.mock('@/lib/auth/auth-client', () => ({
55
}))
66

77
import type { WorkspaceFileRecord } from '@/lib/uploads/contexts/workspace'
8-
import { getRenderableMessageText } from '@/app/workspace/[workspaceId]/home/components/message-content'
8+
import { getOrchestratorMessageText } from '@/app/workspace/[workspaceId]/home/components/message-content'
99
import {
1010
prepareCopyableMarkdown,
1111
serializeCopyableMarkdown,
@@ -173,7 +173,7 @@ describe('toCopyableMarkdown', () => {
173173
expect(refreshWorkspaceFiles).not.toHaveBeenCalled()
174174
})
175175

176-
it('copies workspace resources from visible content blocks', () => {
176+
it('copies workspace resources from orchestrator content blocks', () => {
177177
const contentBlocks: ContentBlock[] = [
178178
{ type: 'text', content: 'Read ' },
179179
{ type: 'thinking', content: 'Do not copy this.' },
@@ -184,7 +184,7 @@ describe('toCopyableMarkdown', () => {
184184
},
185185
]
186186

187-
const content = getRenderableMessageText(contentBlocks, 'Fallback without the resource.')
187+
const content = getOrchestratorMessageText(contentBlocks, 'Fallback without the resource.')
188188

189189
expect(toCopyableMarkdown(content, WORKSPACE_FILES)).toBe(
190190
'Read [notes.md](sim:file/files/notes.md) for details.'

apps/sim/app/workspace/[workspaceId]/home/components/mothership-chat/mothership-chat.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { ChatMessageAttachments } from '@/app/workspace/[workspaceId]/home/compo
2020
import { ChatSurfaceProvider } from '@/app/workspace/[workspaceId]/home/components/chat-surface-context'
2121
import {
2222
assistantMessageHasRenderableContent,
23-
getRenderableMessageText,
23+
getOrchestratorMessageText,
2424
MessageContent,
2525
type MessagePhase,
2626
} from '@/app/workspace/[workspaceId]/home/components/message-content'
@@ -237,7 +237,7 @@ const AssistantMessageRow = memo(function AssistantMessageRow({
237237
}, [phase])
238238

239239
const getCopyContent = useCallback(
240-
() => getRenderableMessageText(blocks, message.content),
240+
() => getOrchestratorMessageText(blocks, message.content),
241241
[blocks, message.content]
242242
)
243243
const prepareContentForCopy = useCallback(
@@ -302,7 +302,7 @@ const AssistantMessageRow = memo(function AssistantMessageRow({
302302
<MessageActions
303303
content={message.content}
304304
getCopyContent={getCopyContent}
305-
hasCopyContent={Boolean(getRenderableMessageText(blocks, message.content).trim())}
305+
hasCopyContent={Boolean(getOrchestratorMessageText(blocks, message.content).trim())}
306306
prepareContentForCopy={prepareContentForCopy}
307307
userQuery={precedingUserContent}
308308
requestId={message.requestId}

0 commit comments

Comments
 (0)