Skip to content

Commit 73a07b9

Browse files
committed
fix(subagents): thinking lanes
1 parent 7678b42 commit 73a07b9

2 files changed

Lines changed: 48 additions & 3 deletions

File tree

apps/sim/lib/copilot/chat/effective-transcript.test.ts

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ describe('buildEffectiveChatTranscript', () => {
154154
)
155155
})
156156

157-
it('does not duplicate thinking-only text into a second assistant block', () => {
157+
it('never surfaces thinking-channel text: a thinking-only stream stays a placeholder', () => {
158158
const result = buildEffectiveChatTranscript({
159159
messages: [buildUserMessage('stream-1', 'Hello')],
160160
activeStreamId: 'stream-1',
@@ -180,15 +180,51 @@ describe('buildEffectiveChatTranscript', () => {
180180
expect(result).toHaveLength(2)
181181
expect(result[1]).toEqual(
182182
expect.objectContaining({
183-
content: 'Internal reasoning',
183+
id: getLiveAssistantMessageId('stream-1'),
184+
role: 'assistant',
185+
content: '',
186+
})
187+
)
188+
expect(JSON.stringify(result[1])).not.toContain('Internal reasoning')
189+
})
190+
191+
it('keeps assistant text while dropping interleaved thinking chunks', () => {
192+
const textEvent = (seq: number, channel: MothershipStreamV1TextChannel, text: string) =>
193+
toBatchEvent(seq, {
194+
v: 1,
195+
seq,
196+
ts: '2026-04-15T12:00:01.000Z',
197+
type: MothershipStreamV1EventType.text,
198+
stream: { streamId: 'stream-1' },
199+
payload: { channel, text },
200+
})
201+
const result = buildEffectiveChatTranscript({
202+
messages: [buildUserMessage('stream-1', 'Hello')],
203+
activeStreamId: 'stream-1',
204+
streamSnapshot: {
205+
events: [
206+
textEvent(1, MothershipStreamV1TextChannel.thinking, '**Planning**\n\nHidden reasoning.'),
207+
textEvent(2, MothershipStreamV1TextChannel.assistant, 'Visible answer.'),
208+
textEvent(3, MothershipStreamV1TextChannel.thinking, 'More hidden reasoning.'),
209+
],
210+
previewSessions: [],
211+
status: 'active',
212+
},
213+
})
214+
215+
expect(result).toHaveLength(2)
216+
expect(result[1]).toEqual(
217+
expect.objectContaining({
218+
content: 'Visible answer.',
184219
contentBlocks: [
185220
expect.objectContaining({
186221
type: MothershipStreamV1EventType.text,
187-
content: 'Internal reasoning',
222+
content: 'Visible answer.',
188223
}),
189224
],
190225
})
191226
)
227+
expect(JSON.stringify(result[1])).not.toContain('reasoning')
192228
})
193229

194230
it('treats user-cancelled tool results as cancelled', () => {

apps/sim/lib/copilot/chat/effective-transcript.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
MothershipStreamV1SessionKind,
1010
MothershipStreamV1SpanLifecycleEvent,
1111
MothershipStreamV1SpanPayloadKind,
12+
MothershipStreamV1TextChannel,
1213
MothershipStreamV1ToolOutcome,
1314
MothershipStreamV1ToolPhase,
1415
} from '@/lib/copilot/generated/mothership-stream-v1'
@@ -263,6 +264,14 @@ function buildLiveAssistantMessage(params: {
263264
if (!chunk) {
264265
continue
265266
}
267+
// Reasoning is never rendered or persisted (the stream reducer and the
268+
// turn model both key on the channel; buildPersistedAssistantMessage
269+
// strips it). This snapshot-derived converter must not resurrect it as
270+
// visible prose — skip before block append AND runningText so thinking
271+
// never leaks into the live-assistant message's content either.
272+
if (parsed.payload.channel === MothershipStreamV1TextChannel.thinking) {
273+
continue
274+
}
266275
const contentSource: 'main' | 'subagent' = scopedSubagent ? 'subagent' : 'main'
267276
const needsBoundaryNewline =
268277
lastContentSource !== null &&

0 commit comments

Comments
 (0)