diff --git a/apps/desktop/src/app/chat/composer/status-stack/index.tsx b/apps/desktop/src/app/chat/composer/status-stack/index.tsx index 93c8a2dc1af..df394e20323 100644 --- a/apps/desktop/src/app/chat/composer/status-stack/index.tsx +++ b/apps/desktop/src/app/chat/composer/status-stack/index.tsx @@ -118,48 +118,59 @@ export function ComposerStatusStack({ queue, sessionId }: ComposerStatusStackPro const hasBackgroundGroup = groups.some(g => g.type === 'background') - const sections: { key: string; node: ReactNode }[] = groups.map(group => ({ - key: group.type, - node: ( - - {t.statusStack.agents} - - ) : undefined - } - defaultCollapsed={group.type !== 'todo'} - icon={} - label={groupLabel(group, t.statusStack)} - > - {group.items.map(item => ( - dismissBackgroundProcess(sessionId, id) : undefined} - onOpen={() => openSubagent(item)} - onStop={sessionId ? id => void stopBackgroundProcess(sessionId, id) : undefined} - /> - ))} - {group.type === 'background' && previewRows} - - ) - })) + const previewBlock =
{previewRows}
+ + const sections: { key: string; node: ReactNode }[] = [] + + for (const group of groups) { + sections.push({ + key: group.type, + node: ( + + {t.statusStack.agents} + + ) : undefined + } + defaultCollapsed={group.type !== 'todo'} + icon={} + label={groupLabel(group, t.statusStack)} + > + {group.items.map(item => ( + dismissBackgroundProcess(sessionId, id) : undefined} + onOpen={() => openSubagent(item)} + onStop={sessionId ? id => void stopBackgroundProcess(sessionId, id) : undefined} + /> + ))} + + ) + }) + + // Preview links belong to the background group (a localhost dev server and + // its preview are the same thing), but they must stay VISIBLE even when that + // group is collapsed — the whole point is a one-tap open. Render them as an + // always-visible block right after the background section, not as collapsible + // children that get swallowed the moment a background task appears. + if (group.type === 'background' && previewRows.length > 0) { + sections.push({ key: 'preview', node: previewBlock }) + } + } // No background group to host them (e.g. a standalone on-disk file preview): - // keep the previews as their own row block so they don't disappear. + // still render them as their own always-visible block. if (previewRows.length > 0 && !hasBackgroundGroup) { - sections.push({ - key: 'preview', - node:
{previewRows}
- }) + sections.push({ key: 'preview', node: previewBlock }) } if (queue) {