diff --git a/packages/ui/src/components/chat/MessageList.tsx b/packages/ui/src/components/chat/MessageList.tsx index 7d3c73d5..4a162760 100644 --- a/packages/ui/src/components/chat/MessageList.tsx +++ b/packages/ui/src/components/chat/MessageList.tsx @@ -1021,6 +1021,10 @@ const TimelineList = React.memo(({ rowContext, }: TimelineListProps) => { const listRef = React.useRef(null); + // With streaming auto-follow off, content growth must never move the + // viewport; explicit commands (the scroll-to-bottom pill, session open) + // still scroll through the imperative handle. + const streamingAutoFollowEnabled = useUIStore((state) => state.streamingAutoFollowEnabled); const isAtEndRef = React.useRef(true); const setListRef = React.useCallback((list: LegendListRef | null) => { @@ -1067,7 +1071,7 @@ const TimelineList = React.memo(({ contentInsetEndAdjustment={composerOverlayHeight} // While a turn is anchored, the reserved end space — not the // live edge — defines where the viewport rests. - maintainScrollAtEnd={anchoredEndSpace + maintainScrollAtEnd={anchoredEndSpace || !streamingAutoFollowEnabled ? false : { animated: false, on: { dataChange: true, itemLayout: true, layout: true } }} // Prepending older history must not move what the user is diff --git a/packages/ui/src/components/sections/openchamber/OpenChamberVisualSettings.tsx b/packages/ui/src/components/sections/openchamber/OpenChamberVisualSettings.tsx index 60313ff1..f7d203fc 100644 --- a/packages/ui/src/components/sections/openchamber/OpenChamberVisualSettings.tsx +++ b/packages/ui/src/components/sections/openchamber/OpenChamberVisualSettings.tsx @@ -302,6 +302,8 @@ export const OpenChamberVisualSettings: React.FC const sessionGoalDefaultBudget = useUIStore(state => state.sessionGoalDefaultBudget); const setSessionGoalDefaultBudget = useUIStore(state => state.setSessionGoalDefaultBudget); const setShowReasoningTraces = useUIStore(state => state.setShowReasoningTraces); + const streamingAutoFollowEnabled = useUIStore(state => state.streamingAutoFollowEnabled); + const setStreamingAutoFollowEnabled = useUIStore(state => state.setStreamingAutoFollowEnabled); const collapsibleThinkingBlocks = useUIStore(state => state.collapsibleThinkingBlocks); const setCollapsibleThinkingBlocks = useUIStore(state => state.setCollapsibleThinkingBlocks); @@ -1839,6 +1841,20 @@ export const OpenChamberVisualSettings: React.FC )} )} + + + {(shouldShow('collapsibleUserMessages') || shouldShow('stickyUserHeader') || (shouldShow('promptNavigatorEnabled') && !isVSCode) || shouldShow('wideChatLayout') || shouldShow('splitAssistantMessageActions') || shouldShow('codeBlockLineWrap')) && ( state.streamingAutoFollowEnabled); + const streamingAutoFollowEnabledRef = React.useRef(streamingAutoFollowEnabled); + streamingAutoFollowEnabledRef.current = streamingAutoFollowEnabled; + const onTimelineDataChange = React.useCallback(() => { + if (!streamingAutoFollowEnabledRef.current) return; if (!isLiveFollowActive()) return; // Following the end needs no animation frames: the totalSize listener diff --git a/packages/ui/src/lib/appearanceAutoSave.ts b/packages/ui/src/lib/appearanceAutoSave.ts index efca7976..44fda25a 100644 --- a/packages/ui/src/lib/appearanceAutoSave.ts +++ b/packages/ui/src/lib/appearanceAutoSave.ts @@ -7,6 +7,7 @@ import type { TerminalShell } from '@/lib/api/types'; type AppearanceSlice = { showReasoningTraces: boolean; + streamingAutoFollowEnabled: boolean; workStatusPanelEnabled: boolean; workStatusHiddenSections: string[]; sessionRecapEnabled: boolean; @@ -62,6 +63,7 @@ export const startAppearanceAutoSave = (): void => { let previous: AppearanceSlice = { showReasoningTraces: useUIStore.getState().showReasoningTraces, + streamingAutoFollowEnabled: useUIStore.getState().streamingAutoFollowEnabled, workStatusPanelEnabled: useUIStore.getState().workStatusPanelEnabled, workStatusHiddenSections: useUIStore.getState().workStatusHiddenSections, sessionRecapEnabled: useUIStore.getState().sessionRecapEnabled, @@ -104,6 +106,7 @@ export const startAppearanceAutoSave = (): void => { useUIStore.subscribe((state) => { const current: AppearanceSlice = { showReasoningTraces: state.showReasoningTraces, + streamingAutoFollowEnabled: state.streamingAutoFollowEnabled, workStatusPanelEnabled: state.workStatusPanelEnabled, workStatusHiddenSections: state.workStatusHiddenSections, sessionRecapEnabled: state.sessionRecapEnabled, @@ -156,6 +159,9 @@ export const startAppearanceAutoSave = (): void => { if (current.showReasoningTraces !== previous.showReasoningTraces) { diff.showReasoningTraces = current.showReasoningTraces; } + if (current.streamingAutoFollowEnabled !== previous.streamingAutoFollowEnabled) { + diff.streamingAutoFollowEnabled = current.streamingAutoFollowEnabled; + } if (current.sessionRecapEnabled !== previous.sessionRecapEnabled) { diff.sessionRecapEnabled = current.sessionRecapEnabled; } diff --git a/packages/ui/src/lib/desktop.ts b/packages/ui/src/lib/desktop.ts index 3d7a0ebe..1163515d 100644 --- a/packages/ui/src/lib/desktop.ts +++ b/packages/ui/src/lib/desktop.ts @@ -131,6 +131,7 @@ export type DesktopSettings = { defaultVariant?: string; defaultAgent?: string; smallModelUseDefault?: boolean; + streamingAutoFollowEnabled?: boolean; sessionRecapEnabled?: boolean; sessionSuggestionEnabled?: boolean; sessionGoalEnabled?: boolean; diff --git a/packages/ui/src/lib/i18n/messages/de.settings.ts b/packages/ui/src/lib/i18n/messages/de.settings.ts index cf20c06d..1f1a2f48 100644 --- a/packages/ui/src/lib/i18n/messages/de.settings.ts +++ b/packages/ui/src/lib/i18n/messages/de.settings.ts @@ -1856,6 +1856,10 @@ export const settingsDict = { 'settings.openchamber.visual.section.showToolsOpenedByDefault': 'Werkzeuge standardmäßig geöffnet anzeigen:', 'settings.openchamber.visual.section.sessionAssistance': 'Sitzungshilfe', 'settings.openchamber.visual.section.reasoning': 'Reasoning', + 'settings.openchamber.visual.section.streaming': 'Streaming', + 'settings.openchamber.visual.field.streamingAutoFollow': 'Neuen Inhalten beim Streaming folgen', + 'settings.openchamber.visual.field.streamingAutoFollowAria': 'Neuen Inhalten automatisch folgen, während eine Antwort gestreamt wird', + 'settings.openchamber.visual.field.streamingAutoFollowInfo': 'Während eine Antwort eintrifft, folgt die Ansicht laufend dem neuesten Inhalt. Deaktivieren, um die Ansicht ruhig zu halten und manuell zu scrollen.', 'settings.openchamber.visual.section.messageAppearance': 'Nachrichten-Erscheinungsbild', 'settings.openchamber.visual.section.toolsAndFiles': 'Werkzeuge & Dateien', 'settings.openchamber.visual.section.composer': 'Komponist', diff --git a/packages/ui/src/lib/i18n/messages/en.settings.ts b/packages/ui/src/lib/i18n/messages/en.settings.ts index a1e1435f..b8718cda 100644 --- a/packages/ui/src/lib/i18n/messages/en.settings.ts +++ b/packages/ui/src/lib/i18n/messages/en.settings.ts @@ -1929,6 +1929,10 @@ export const settingsDict = { 'settings.openchamber.visual.section.showToolsOpenedByDefault': 'Show tools opened by default', 'settings.openchamber.visual.section.sessionAssistance': 'Session Assistance', 'settings.openchamber.visual.section.reasoning': 'Reasoning', + 'settings.openchamber.visual.section.streaming': 'Streaming', + 'settings.openchamber.visual.field.streamingAutoFollow': 'Follow new content while streaming', + 'settings.openchamber.visual.field.streamingAutoFollowAria': 'Automatically follow new content while a response streams', + 'settings.openchamber.visual.field.streamingAutoFollowInfo': 'While a reply streams in, the view keeps gliding to the newest content. Turn this off to keep the view still and scroll manually.', 'settings.openchamber.visual.section.messageAppearance': 'Message Appearance', 'settings.openchamber.visual.section.toolsAndFiles': 'Tools & Files', 'settings.openchamber.visual.section.composer': 'Composer', diff --git a/packages/ui/src/lib/i18n/messages/es.settings.ts b/packages/ui/src/lib/i18n/messages/es.settings.ts index 064a329f..b05c568c 100644 --- a/packages/ui/src/lib/i18n/messages/es.settings.ts +++ b/packages/ui/src/lib/i18n/messages/es.settings.ts @@ -1906,6 +1906,10 @@ export const settingsDict = { "settings.openchamber.visual.section.showToolsOpenedByDefault": "Mostrar herramientas abiertas por defecto", "settings.openchamber.visual.section.sessionAssistance": "Asistencia de sesión", "settings.openchamber.visual.section.reasoning": "Razonamiento", + "settings.openchamber.visual.section.streaming": "Streaming", + "settings.openchamber.visual.field.streamingAutoFollow": "Seguir el contenido nuevo durante el streaming", + "settings.openchamber.visual.field.streamingAutoFollowAria": "Seguir automáticamente el contenido nuevo mientras se transmite una respuesta", + "settings.openchamber.visual.field.streamingAutoFollowInfo": "Mientras llega una respuesta, la vista se desplaza hacia el contenido más reciente. Desactívalo para mantener la vista quieta y desplazarte manualmente.", "settings.openchamber.visual.section.messageAppearance": "Apariencia de los mensajes", "settings.openchamber.visual.section.toolsAndFiles": "Herramientas y archivos", "settings.openchamber.visual.section.composer": "Compositor", diff --git a/packages/ui/src/lib/i18n/messages/fr.settings.ts b/packages/ui/src/lib/i18n/messages/fr.settings.ts index ae539b59..345e0c08 100644 --- a/packages/ui/src/lib/i18n/messages/fr.settings.ts +++ b/packages/ui/src/lib/i18n/messages/fr.settings.ts @@ -1820,6 +1820,10 @@ export const settingsDict = { 'settings.openchamber.visual.section.showToolsOpenedByDefault': 'Afficher les outils ouverts par défaut', 'settings.openchamber.visual.section.sessionAssistance': 'Assistance de session', 'settings.openchamber.visual.section.reasoning': 'Raisonnement', + 'settings.openchamber.visual.section.streaming': 'Streaming', + 'settings.openchamber.visual.field.streamingAutoFollow': 'Suivre le nouveau contenu pendant le streaming', + 'settings.openchamber.visual.field.streamingAutoFollowAria': 'Suivre automatiquement le nouveau contenu pendant la diffusion d’une réponse', + 'settings.openchamber.visual.field.streamingAutoFollowInfo': 'Pendant qu’une réponse arrive, la vue glisse vers le contenu le plus récent. Désactivez pour garder la vue immobile et défiler manuellement.', 'settings.openchamber.visual.section.messageAppearance': 'Apparence des messages', 'settings.openchamber.visual.section.toolsAndFiles': 'Outils et fichiers', 'settings.openchamber.visual.section.composer': 'Zone de saisie', diff --git a/packages/ui/src/lib/i18n/messages/ja.settings.ts b/packages/ui/src/lib/i18n/messages/ja.settings.ts index 24db27fe..8d6f1c1b 100644 --- a/packages/ui/src/lib/i18n/messages/ja.settings.ts +++ b/packages/ui/src/lib/i18n/messages/ja.settings.ts @@ -1939,6 +1939,10 @@ export const settingsDict = { 'settings.openchamber.visual.section.showToolsOpenedByDefault': 'デフォルトで開くツールを表示', 'settings.openchamber.visual.section.sessionAssistance': 'セッション支援', 'settings.openchamber.visual.section.reasoning': '推論', + 'settings.openchamber.visual.section.streaming': 'ストリーミング', + 'settings.openchamber.visual.field.streamingAutoFollow': '応答のストリーミング中に新しい内容を追従', + 'settings.openchamber.visual.field.streamingAutoFollowAria': '応答のストリーミング中に新しい内容へ自動スクロールする', + 'settings.openchamber.visual.field.streamingAutoFollowInfo': '応答の受信中、ビューは常に最新の内容へスクロールします。オフにするとビューは動かず、手動でスクロールできます。', 'settings.openchamber.visual.section.messageAppearance': 'メッセージの外観', 'settings.openchamber.visual.section.toolsAndFiles': 'ツールとファイル', 'settings.openchamber.visual.section.composer': '入力欄', diff --git a/packages/ui/src/lib/i18n/messages/ko.settings.ts b/packages/ui/src/lib/i18n/messages/ko.settings.ts index a2a025f3..07a8e7d0 100644 --- a/packages/ui/src/lib/i18n/messages/ko.settings.ts +++ b/packages/ui/src/lib/i18n/messages/ko.settings.ts @@ -1906,6 +1906,10 @@ export const settingsDict = { 'settings.openchamber.visual.section.showToolsOpenedByDefault': '도구를 기본으로 펼쳐 표시', 'settings.openchamber.visual.section.sessionAssistance': '세션 지원', 'settings.openchamber.visual.section.reasoning': '추론', + 'settings.openchamber.visual.section.streaming': '스트리밍', + 'settings.openchamber.visual.field.streamingAutoFollow': '스트리밍 중 새 내용 따라가기', + 'settings.openchamber.visual.field.streamingAutoFollowAria': '응답 스트리밍 중 새 내용으로 자동 스크롤', + 'settings.openchamber.visual.field.streamingAutoFollowInfo': '응답이 스트리밍되는 동안 화면이 최신 내용으로 계속 이동합니다. 끄면 화면이 고정되어 직접 스크롤할 수 있습니다.', 'settings.openchamber.visual.section.messageAppearance': '메시지 모양', 'settings.openchamber.visual.section.toolsAndFiles': '도구 및 파일', 'settings.openchamber.visual.section.composer': '입력창', diff --git a/packages/ui/src/lib/i18n/messages/pl.settings.ts b/packages/ui/src/lib/i18n/messages/pl.settings.ts index 352c9c14..1ce9c512 100644 --- a/packages/ui/src/lib/i18n/messages/pl.settings.ts +++ b/packages/ui/src/lib/i18n/messages/pl.settings.ts @@ -1209,6 +1209,10 @@ export const settingsDict = { 'settings.openchamber.visual.section.showToolsOpenedByDefault': 'Pokaż narzędzia domyślnie otwarte', 'settings.openchamber.visual.section.sessionAssistance': 'Wsparcie sesji', 'settings.openchamber.visual.section.reasoning': 'Rozumowanie', + 'settings.openchamber.visual.section.streaming': 'Streaming', + 'settings.openchamber.visual.field.streamingAutoFollow': 'Podążaj za nową treścią podczas streamingu', + 'settings.openchamber.visual.field.streamingAutoFollowAria': 'Automatycznie podążaj za nową treścią podczas streamowania odpowiedzi', + 'settings.openchamber.visual.field.streamingAutoFollowInfo': 'Podczas napływania odpowiedzi widok płynnie podąża za najnowszą treścią. Wyłącz, aby widok pozostał nieruchomy i przewijać ręcznie.', 'settings.openchamber.visual.section.messageAppearance': 'Wygląd wiadomości', 'settings.openchamber.visual.section.toolsAndFiles': 'Narzędzia i pliki', 'settings.openchamber.visual.section.composer': 'Pole wiadomości', diff --git a/packages/ui/src/lib/i18n/messages/pt-BR.settings.ts b/packages/ui/src/lib/i18n/messages/pt-BR.settings.ts index 01743896..f095bb16 100644 --- a/packages/ui/src/lib/i18n/messages/pt-BR.settings.ts +++ b/packages/ui/src/lib/i18n/messages/pt-BR.settings.ts @@ -1906,6 +1906,10 @@ export const settingsDict = { "settings.openchamber.visual.section.showToolsOpenedByDefault": "Mostrar ferramentas abertas por padrão", "settings.openchamber.visual.section.sessionAssistance": "Assistência da sessão", "settings.openchamber.visual.section.reasoning": "Raciocínio", + "settings.openchamber.visual.section.streaming": "Streaming", + "settings.openchamber.visual.field.streamingAutoFollow": "Seguir o novo conteúdo durante o streaming", + "settings.openchamber.visual.field.streamingAutoFollowAria": "Seguir automaticamente o novo conteúdo enquanto uma resposta é transmitida", + "settings.openchamber.visual.field.streamingAutoFollowInfo": "Enquanto uma resposta chega, a visualização acompanha o conteúdo mais recente. Desative para manter a visualização parada e rolar manualmente.", "settings.openchamber.visual.section.messageAppearance": "Aparência das mensagens", "settings.openchamber.visual.section.toolsAndFiles": "Ferramentas e arquivos", "settings.openchamber.visual.section.composer": "Campo de mensagem", diff --git a/packages/ui/src/lib/i18n/messages/uk.settings.ts b/packages/ui/src/lib/i18n/messages/uk.settings.ts index 887f359b..49c34b87 100644 --- a/packages/ui/src/lib/i18n/messages/uk.settings.ts +++ b/packages/ui/src/lib/i18n/messages/uk.settings.ts @@ -1906,6 +1906,10 @@ export const settingsDict = { "settings.openchamber.visual.section.showToolsOpenedByDefault": "Показувати інструменти відкритими за замовчуванням", "settings.openchamber.visual.section.sessionAssistance": "Допомога із сесією", "settings.openchamber.visual.section.reasoning": "Міркування", + "settings.openchamber.visual.section.streaming": "Стримінг", + "settings.openchamber.visual.field.streamingAutoFollow": "Слідкувати за новим вмістом під час стримінгу", + "settings.openchamber.visual.field.streamingAutoFollowAria": "Автоматично слідкувати за новим вмістом під час стримінгу відповіді", + "settings.openchamber.visual.field.streamingAutoFollowInfo": "Поки відповідь надходить, вигляд плавно рухається до найновішого вмісту. Вимкніть, щоб вигляд залишався нерухомим і гортати вручну.", "settings.openchamber.visual.section.messageAppearance": "Вигляд повідомлень", "settings.openchamber.visual.section.toolsAndFiles": "Інструменти та файли", "settings.openchamber.visual.section.composer": "Поле вводу", diff --git a/packages/ui/src/lib/i18n/messages/zh-CN.settings.ts b/packages/ui/src/lib/i18n/messages/zh-CN.settings.ts index d8b99d7f..7874ce8e 100644 --- a/packages/ui/src/lib/i18n/messages/zh-CN.settings.ts +++ b/packages/ui/src/lib/i18n/messages/zh-CN.settings.ts @@ -1906,6 +1906,10 @@ export const settingsDict = { 'settings.openchamber.visual.section.showToolsOpenedByDefault': '默认展开以下工具', 'settings.openchamber.visual.section.sessionAssistance': '会话辅助', 'settings.openchamber.visual.section.reasoning': '推理', + 'settings.openchamber.visual.section.streaming': '流式输出', + 'settings.openchamber.visual.field.streamingAutoFollow': '流式输出时跟随新内容', + 'settings.openchamber.visual.field.streamingAutoFollowAria': '在回复流式输出时自动跟随新内容', + 'settings.openchamber.visual.field.streamingAutoFollowInfo': '回复流式输出时,视图会持续滚动到最新内容。关闭后视图保持不动,可手动滚动。', 'settings.openchamber.visual.section.messageAppearance': '消息外观', 'settings.openchamber.visual.section.toolsAndFiles': '工具和文件', 'settings.openchamber.visual.section.composer': '输入框', diff --git a/packages/ui/src/lib/i18n/messages/zh-TW.settings.ts b/packages/ui/src/lib/i18n/messages/zh-TW.settings.ts index 99ddd925..273a5631 100644 --- a/packages/ui/src/lib/i18n/messages/zh-TW.settings.ts +++ b/packages/ui/src/lib/i18n/messages/zh-TW.settings.ts @@ -1813,6 +1813,10 @@ export const settingsDict = { 'settings.openchamber.visual.section.showToolsOpenedByDefault': '預設展開以下工具', 'settings.openchamber.visual.section.sessionAssistance': '工作階段輔助', 'settings.openchamber.visual.section.reasoning': '推理', + 'settings.openchamber.visual.section.streaming': '串流', + 'settings.openchamber.visual.field.streamingAutoFollow': '串流時跟隨新內容', + 'settings.openchamber.visual.field.streamingAutoFollowAria': '回覆串流時自動跟隨新內容', + 'settings.openchamber.visual.field.streamingAutoFollowInfo': '回覆串流時,畫面會持續捲動到最新內容。關閉後畫面保持不動,可手動捲動。', 'settings.openchamber.visual.section.messageAppearance': '訊息外觀', 'settings.openchamber.visual.section.toolsAndFiles': '工具與檔案', 'settings.openchamber.visual.section.composer': '輸入框', diff --git a/packages/ui/src/lib/persistence.ts b/packages/ui/src/lib/persistence.ts index 7d3ca54c..f24c7a2b 100644 --- a/packages/ui/src/lib/persistence.ts +++ b/packages/ui/src/lib/persistence.ts @@ -531,6 +531,7 @@ const materializeAuthoritativeUiSettings = (settings: DesktopSettings): DesktopS darkThemeId: DEFAULT_DARK_THEME_ID, openInAppId: DEFAULT_OPEN_IN_APP_ID, showReasoningTraces: defaults.showReasoningTraces, + streamingAutoFollowEnabled: defaults.streamingAutoFollowEnabled, workStatusPanelEnabled: defaults.workStatusPanelEnabled, workStatusHiddenSections: defaults.workStatusHiddenSections, sessionRecapEnabled: defaults.sessionRecapEnabled, @@ -637,6 +638,9 @@ const applyDesktopUiPreferences = (settings: DesktopSettings) => { if (typeof settings.showReasoningTraces === 'boolean' && settings.showReasoningTraces !== store.showReasoningTraces) { store.setShowReasoningTraces(settings.showReasoningTraces); } + if (typeof settings.streamingAutoFollowEnabled === 'boolean' && settings.streamingAutoFollowEnabled !== store.streamingAutoFollowEnabled) { + store.setStreamingAutoFollowEnabled(settings.streamingAutoFollowEnabled); + } if (typeof settings.sessionRecapEnabled === 'boolean' && settings.sessionRecapEnabled !== store.sessionRecapEnabled) { store.setSessionRecapEnabled(settings.sessionRecapEnabled); } @@ -1158,6 +1162,9 @@ const sanitizeWebSettings = (payload: unknown): DesktopSettings | null => { if (typeof candidate.showReasoningTraces === 'boolean') { result.showReasoningTraces = candidate.showReasoningTraces; } + if (typeof candidate.streamingAutoFollowEnabled === 'boolean') { + result.streamingAutoFollowEnabled = candidate.streamingAutoFollowEnabled; + } if (typeof candidate.sessionRecapEnabled === 'boolean') { result.sessionRecapEnabled = candidate.sessionRecapEnabled; } diff --git a/packages/ui/src/lib/settings/search.ts b/packages/ui/src/lib/settings/search.ts index 134c17e4..2716e7ca 100644 --- a/packages/ui/src/lib/settings/search.ts +++ b/packages/ui/src/lib/settings/search.ts @@ -240,6 +240,19 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [ titleKey: 'settings.openchamber.visual.section.reasoning', keywords: ['thinking', 'traces'], }, + { + id: 'chat.streaming', + page: 'chat', + titleKey: 'settings.openchamber.visual.section.streaming', + keywords: ['stream', 'scroll'], + }, + { + id: 'chat.streaming-auto-follow', + page: 'chat', + titleKey: 'settings.openchamber.visual.field.streamingAutoFollow', + descriptionKey: 'settings.openchamber.visual.field.streamingAutoFollowInfo', + keywords: ['autoscroll', 'auto-scroll', 'follow', 'stick to bottom', 'streaming'], + }, { id: 'chat.sticky-user-header', page: 'chat', diff --git a/packages/ui/src/stores/useUIStore.ts b/packages/ui/src/stores/useUIStore.ts index 812a5ffe..e24e8ead 100644 --- a/packages/ui/src/stores/useUIStore.ts +++ b/packages/ui/src/stores/useUIStore.ts @@ -674,6 +674,7 @@ interface UIStore { eventStreamStatus: EventStreamStatus; eventStreamHint: string | null; showReasoningTraces: boolean; + streamingAutoFollowEnabled: boolean; sessionRecapEnabled: boolean; sessionSuggestionEnabled: boolean; sessionGoalEnabled: boolean; @@ -859,6 +860,7 @@ interface UIStore { setSettingsRemoteInstancesSelectedId: (instanceId: string | null) => void; setEventStreamStatus: (status: EventStreamStatus, hint?: string | null) => void; setShowReasoningTraces: (value: boolean) => void; + setStreamingAutoFollowEnabled: (value: boolean) => void; setSessionRecapEnabled: (value: boolean) => void; setSessionSuggestionEnabled: (value: boolean) => void; setSessionGoalEnabled: (value: boolean) => void; @@ -1027,6 +1029,7 @@ export const useUIStore = create()( eventStreamStatus: 'idle', eventStreamHint: null, showReasoningTraces: true, + streamingAutoFollowEnabled: true, sessionRecapEnabled: true, sessionSuggestionEnabled: true, sessionGoalEnabled: true, @@ -1759,6 +1762,10 @@ export const useUIStore = create()( set({ showReasoningTraces: value }); }, + setStreamingAutoFollowEnabled: (value) => { + set({ streamingAutoFollowEnabled: value }); + }, + setSessionRecapEnabled: (value) => { set({ sessionRecapEnabled: value }); }, @@ -2639,6 +2646,7 @@ export const useUIStore = create()( isSessionCreateDialogOpen: state.isSessionCreateDialogOpen, // Note: isSettingsDialogOpen intentionally NOT persisted showReasoningTraces: state.showReasoningTraces, + streamingAutoFollowEnabled: state.streamingAutoFollowEnabled, sessionRecapEnabled: state.sessionRecapEnabled, sessionSuggestionEnabled: state.sessionSuggestionEnabled, sessionGoalEnabled: state.sessionGoalEnabled,