Show reasoning output automatically when enabled (#1943)

* feat(app): add auto-expand reasoning setting

* chore: add cross-env mise tool

* fix(app): stabilize web export and settings detail placement

* Revert "chore: add cross-env mise tool"

This reverts commit f56a367e0cd6766140db2d3b30a1c57bff4d9a14.

* perf(app): narrow settings reads in agent stream

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
This commit is contained in:
Matt Cowger
2026-07-08 21:39:03 +00:00
committed by GitHub
co-authored by Mohamed Boudra
parent 29a3261dd6
commit d96d599466
15 changed files with 155 additions and 19 deletions
+2
View File
@@ -303,6 +303,8 @@ npm run build:app-deps # highlight -> protocol -> client -> expo-two-way-aud
Use `npm run build:server` whenever you have changed any daemon/server-facing package and need clean cross-package types or runtime behavior. Use `npm run build:server` whenever you have changed any daemon/server-facing package and need clean cross-package types or runtime behavior.
The app Metro config disables Watchman and uses Metro's node crawler for exports. Keep that invariant unless you have verified production app exports on machines with and without Watchman installed; distro Watchman builds can differ in capabilities and change Metro's crawl behavior.
For tighter loops, you can rebuild a single workspace: For tighter loops, you can rebuild a single workspace:
- Changed `packages/protocol/src/*` or `packages/client/src/*`: `npm run build:client`. - Changed `packages/protocol/src/*` or `packages/client/src/*`: `npm run build:client`.
+6
View File
@@ -14,6 +14,12 @@ const customWebPlatform = (process.env.PASEO_WEB_PLATFORM ?? "")
const config = getDefaultConfig(projectRoot); const config = getDefaultConfig(projectRoot);
const defaultResolveRequest = config.resolver.resolveRequest ?? resolve; const defaultResolveRequest = config.resolver.resolveRequest ?? resolve;
// Keep app exports deterministic across dev machines and CI. Metro's Watchman
// crawler behavior depends on the host Watchman build/capabilities, while the
// node crawler is the path used when Watchman is absent.
config.resolver.useWatchman = false;
const escapedAppSrcRoot = appSrcRoot const escapedAppSrcRoot = appSrcRoot
.split(path.sep) .split(path.sep)
.map((segment) => segment.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&")) .map((segment) => segment.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&"))
+5 -1
View File
@@ -52,6 +52,7 @@ import type { AgentScreenAgent } from "@/hooks/use-agent-screen-state-machine";
import { useSessionStore } from "@/stores/session-store"; import { useSessionStore } from "@/stores/session-store";
import { useFileExplorerActions } from "@/hooks/use-file-explorer-actions"; import { useFileExplorerActions } from "@/hooks/use-file-explorer-actions";
import { useLoadOlderAgentHistory } from "@/hooks/use-load-older-agent-history"; import { useLoadOlderAgentHistory } from "@/hooks/use-load-older-agent-history";
import { useSettings } from "@/hooks/use-settings";
import type { ToastApi } from "@/components/toast-host"; import type { ToastApi } from "@/components/toast-host";
import type { DaemonClient } from "@getpaseo/client/internal/daemon-client"; import type { DaemonClient } from "@getpaseo/client/internal/daemon-client";
import { ToolCallDetailsContent } from "@/components/tool-call-details"; import { ToolCallDetailsContent } from "@/components/tool-call-details";
@@ -318,6 +319,7 @@ const AgentStreamViewComponent = forwardRef<AgentStreamViewHandle, AgentStreamVi
) { ) {
const { t } = useTranslation(); const { t } = useTranslation();
const router = useRouter(); const router = useRouter();
const autoExpandReasoning = useSettings((settings) => settings.autoExpandReasoning);
const viewportRef = useRef<StreamViewportHandle | null>(null); const viewportRef = useRef<StreamViewportHandle | null>(null);
const isMobile = useIsCompactFormFactor(); const isMobile = useIsCompactFormFactor();
const streamRenderStrategy = useMemo( const streamRenderStrategy = useMemo(
@@ -633,10 +635,12 @@ const AgentStreamViewComponent = forwardRef<AgentStreamViewHandle, AgentStreamVi
args={item.text} args={item.text}
status={item.status === "ready" ? "completed" : "executing"} status={item.status === "ready" ? "completed" : "executing"}
isLastInSequence={layoutItem.isLastInToolSequence} isLastInSequence={layoutItem.isLastInToolSequence}
defaultExpanded={autoExpandReasoning}
forceInline={autoExpandReasoning}
/> />
); );
}, },
[setInlineDetailsExpanded], [autoExpandReasoning, setInlineDetailsExpanded],
); );
const renderToolCallItem = useCallback( const renderToolCallItem = useCallback(
+18 -11
View File
@@ -3038,6 +3038,8 @@ interface ToolCallProps {
onInlineDetailsHoverChange?: (hovered: boolean) => void; onInlineDetailsHoverChange?: (hovered: boolean) => void;
onInlineDetailsExpandedChange?: (expanded: boolean) => void; onInlineDetailsExpandedChange?: (expanded: boolean) => void;
onOpenFilePath?: (filePath: string) => void; onOpenFilePath?: (filePath: string) => void;
defaultExpanded?: boolean;
forceInline?: boolean;
} }
export const ToolCall = memo(function ToolCall({ export const ToolCall = memo(function ToolCall({
@@ -3054,11 +3056,14 @@ export const ToolCall = memo(function ToolCall({
onInlineDetailsHoverChange, onInlineDetailsHoverChange,
onInlineDetailsExpandedChange, onInlineDetailsExpandedChange,
onOpenFilePath, onOpenFilePath,
defaultExpanded,
forceInline = false,
}: ToolCallProps) { }: ToolCallProps) {
const { openToolCall } = useToolCallSheet(); const { openToolCall } = useToolCallSheet();
const [isExpanded, setIsExpanded] = useState(false); const [isExpanded, setIsExpanded] = useState(defaultExpanded ?? false);
const isMobile = useIsCompactFormFactor(); const isMobile = useIsCompactFormFactor();
const shouldRenderInline = !isMobile || forceInline;
const effectiveDetail = useMemo<ToolCallDetail | undefined>(() => { const effectiveDetail = useMemo<ToolCallDetail | undefined>(() => {
if (detail) { if (detail) {
@@ -3096,7 +3101,7 @@ export const ToolCall = memo(function ToolCall({
}, [presentation.openFilePath, onOpenFilePath]); }, [presentation.openFilePath, onOpenFilePath]);
const handleToggle = useCallback(() => { const handleToggle = useCallback(() => {
if (isMobile) { if (!shouldRenderInline) {
openToolCall({ openToolCall({
displayName: presentation.displayName, displayName: presentation.displayName,
summary: presentation.summary, summary: presentation.summary,
@@ -3109,7 +3114,7 @@ export const ToolCall = memo(function ToolCall({
setIsExpanded((prev) => !prev); setIsExpanded((prev) => !prev);
} }
}, [ }, [
isMobile, shouldRenderInline,
openToolCall, openToolCall,
presentation.displayName, presentation.displayName,
presentation.summary, presentation.summary,
@@ -3120,22 +3125,22 @@ export const ToolCall = memo(function ToolCall({
]); ]);
useEffect(() => { useEffect(() => {
if (!onInlineDetailsHoverChange || isMobile || isExpanded) { if (!onInlineDetailsHoverChange || !shouldRenderInline || isExpanded) {
return; return;
} }
onInlineDetailsHoverChange(false); onInlineDetailsHoverChange(false);
}, [isExpanded, isMobile, onInlineDetailsHoverChange]); }, [isExpanded, shouldRenderInline, onInlineDetailsHoverChange]);
useEffect(() => { useEffect(() => {
if (!onInlineDetailsExpandedChange) { if (!onInlineDetailsExpandedChange) {
return; return;
} }
if (isMobile) { if (!shouldRenderInline) {
onInlineDetailsExpandedChange(false); onInlineDetailsExpandedChange(false);
return; return;
} }
onInlineDetailsExpandedChange(isExpanded); onInlineDetailsExpandedChange(isExpanded);
}, [isExpanded, isMobile, onInlineDetailsExpandedChange]); }, [isExpanded, shouldRenderInline, onInlineDetailsExpandedChange]);
useEffect(() => { useEffect(() => {
if (!onInlineDetailsExpandedChange) { if (!onInlineDetailsExpandedChange) {
@@ -3148,7 +3153,7 @@ export const ToolCall = memo(function ToolCall({
// Render inline details for desktop // Render inline details for desktop
const renderDetails = useCallback(() => { const renderDetails = useCallback(() => {
if (isMobile) return null; if (!shouldRenderInline) return null;
return ( return (
<ToolCallDetailsContent <ToolCallDetailsContent
detail={effectiveDetail} detail={effectiveDetail}
@@ -3157,7 +3162,7 @@ export const ToolCall = memo(function ToolCall({
showLoadingSkeleton={presentation.isLoadingDetails} showLoadingSkeleton={presentation.isLoadingDetails}
/> />
); );
}, [isMobile, effectiveDetail, presentation.errorText, presentation.isLoadingDetails]); }, [shouldRenderInline, effectiveDetail, presentation.errorText, presentation.isLoadingDetails]);
if (presentation.isPlan && effectiveDetail?.type === "plan") { if (presentation.isPlan && effectiveDetail?.type === "plan") {
return ( return (
@@ -3175,10 +3180,10 @@ export const ToolCall = memo(function ToolCall({
label={presentation.displayName} label={presentation.displayName}
secondaryLabel={presentation.summary} secondaryLabel={presentation.summary}
icon={presentation.icon} icon={presentation.icon}
isExpanded={!isMobile && isExpanded} isExpanded={shouldRenderInline && isExpanded}
onToggle={presentation.canOpenDetails ? handleToggle : undefined} onToggle={presentation.canOpenDetails ? handleToggle : undefined}
onOpenFile={handleOpenFile} onOpenFile={handleOpenFile}
renderDetails={presentation.canOpenDetails && !isMobile ? renderDetails : undefined} renderDetails={presentation.canOpenDetails && shouldRenderInline ? renderDetails : undefined}
isLoading={status === "running" || status === "executing"} isLoading={status === "running" || status === "executing"}
isError={status === "failed"} isError={status === "failed"}
isLastInSequence={isLastInSequence} isLastInSequence={isLastInSequence}
@@ -3200,5 +3205,7 @@ function areToolCallPropsEqual(previous: ToolCallProps, next: ToolCallProps) {
if (previous.isLastInSequence !== next.isLastInSequence) return false; if (previous.isLastInSequence !== next.isLastInSequence) return false;
if (previous.disableOuterSpacing !== next.disableOuterSpacing) return false; if (previous.disableOuterSpacing !== next.disableOuterSpacing) return false;
if (previous.onOpenFilePath !== next.onOpenFilePath) return false; if (previous.onOpenFilePath !== next.onOpenFilePath) return false;
if (previous.defaultExpanded !== next.defaultExpanded) return false;
if (previous.forceInline !== next.forceInline) return false;
return true; return true;
} }
+22 -7
View File
@@ -96,6 +96,8 @@ export interface UseSettingsReturn {
resetSettings: () => Promise<void>; resetSettings: () => Promise<void>;
} }
type SettingsSelector<TSelected> = (settings: Settings) => TSelected;
export function useAppSettings(): UseAppSettingsReturn { export function useAppSettings(): UseAppSettingsReturn {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { data, isPending, error } = useQuery({ const { data, isPending, error } = useQuery({
@@ -137,7 +139,11 @@ export function useAppSettings(): UseAppSettingsReturn {
}; };
} }
export function useSettings(): UseSettingsReturn { export function useSettings(): UseSettingsReturn;
export function useSettings<TSelected>(selector: SettingsSelector<TSelected>): TSelected;
export function useSettings<TSelected>(
selector?: SettingsSelector<TSelected>,
): UseSettingsReturn | TSelected {
const appSettings = useAppSettings(); const appSettings = useAppSettings();
const desktopSettings = useDesktopSettings(); const desktopSettings = useDesktopSettings();
@@ -177,6 +183,9 @@ export function useSettings(): UseSettingsReturn {
if (updates.workspaceTitleSource !== undefined) { if (updates.workspaceTitleSource !== undefined) {
appUpdates.workspaceTitleSource = updates.workspaceTitleSource; appUpdates.workspaceTitleSource = updates.workspaceTitleSource;
} }
if (updates.autoExpandReasoning !== undefined) {
appUpdates.autoExpandReasoning = updates.autoExpandReasoning;
}
const promises: Promise<void>[] = []; const promises: Promise<void>[] = [];
if (Object.keys(appUpdates).length > 0) { if (Object.keys(appUpdates).length > 0) {
promises.push(appSettings.updateSettings(appUpdates)); promises.push(appSettings.updateSettings(appUpdates));
@@ -210,13 +219,19 @@ export function useSettings(): UseSettingsReturn {
await Promise.all(resets); await Promise.all(resets);
}, [appSettings, desktopSettings]); }, [appSettings, desktopSettings]);
const settings = {
...DEFAULT_APP_SETTINGS,
...appSettings.settings,
manageBuiltInDaemon: desktopSettings.settings.daemon.manageBuiltInDaemon,
releaseChannel: desktopSettings.settings.releaseChannel,
};
if (selector) {
return selector(settings);
}
return { return {
settings: { settings,
...DEFAULT_APP_SETTINGS,
...appSettings.settings,
manageBuiltInDaemon: desktopSettings.settings.daemon.manageBuiltInDaemon,
releaseChannel: desktopSettings.settings.releaseChannel,
},
isLoading: appSettings.isLoading || desktopSettings.isLoading, isLoading: appSettings.isLoading || desktopSettings.isLoading,
error: appSettings.error ?? desktopSettings.error, error: appSettings.error ?? desktopSettings.error,
updateSettings, updateSettings,
@@ -39,6 +39,7 @@ export interface AppSettings {
codeFontSize: number; // clamped px, default 12 codeFontSize: number; // clamped px, default 12
syntaxTheme: SyntaxThemeId; // default "one" syntaxTheme: SyntaxThemeId; // default "one"
workspaceTitleSource: WorkspaceTitleSource; workspaceTitleSource: WorkspaceTitleSource;
autoExpandReasoning: boolean;
} }
export interface Settings extends AppSettings { export interface Settings extends AppSettings {
@@ -58,6 +59,7 @@ export const DEFAULT_CLIENT_SETTINGS: AppSettings = {
codeFontSize: DEFAULT_CODE_FONT_SIZE, codeFontSize: DEFAULT_CODE_FONT_SIZE,
syntaxTheme: "one", syntaxTheme: "one",
workspaceTitleSource: "title", workspaceTitleSource: "title",
autoExpandReasoning: false,
}; };
export const DEFAULT_APP_SETTINGS: Settings = { export const DEFAULT_APP_SETTINGS: Settings = {
@@ -204,6 +206,9 @@ function pickAppSettings(stored: Partial<AppSettings>): Partial<AppSettings> {
) { ) {
result.workspaceTitleSource = stored.workspaceTitleSource; result.workspaceTitleSource = stored.workspaceTitleSource;
} }
if (typeof stored.autoExpandReasoning === "boolean") {
result.autoExpandReasoning = stored.autoExpandReasoning;
}
return result; return result;
} }
+7
View File
@@ -1471,6 +1471,10 @@ export const ar: TranslationResources = {
description: "يتم الاحتفاظ بالخطوط في المخزن المؤقت الطرفي المدمج", description: "يتم الاحتفاظ بالخطوط في المخزن المؤقت الطرفي المدمج",
accessibilityLabel: "خطوط التمرير Terminal", accessibilityLabel: "خطوط التمرير Terminal",
}, },
autoExpandReasoning: {
label: "عرض التفكير دائماً",
description: "إظهار تفكير الوكيل وخطوات الاستدلال بشكل كامل بشكل افتراضي",
},
language: { language: {
label: "لغة", label: "لغة",
description: "لغة التطبيق", description: "لغة التطبيق",
@@ -1552,6 +1556,9 @@ export const ar: TranslationResources = {
auto: "نظام", auto: "نظام",
}, },
}, },
detailLevel: {
title: "مستوى التفاصيل",
},
fonts: { fonts: {
title: "الخطوط", title: "الخطوط",
systemDefault: "الافتراضي للنظام", systemDefault: "الافتراضي للنظام",
+7
View File
@@ -1478,6 +1478,10 @@ export const en = {
description: "Lines kept in the built-in terminal buffer", description: "Lines kept in the built-in terminal buffer",
accessibilityLabel: "Terminal scrollback lines", accessibilityLabel: "Terminal scrollback lines",
}, },
autoExpandReasoning: {
label: "Always expand reasoning",
description: "Show agent thinking and chain-of-thought blocks fully expanded by default",
},
language: { language: {
label: "Language", label: "Language",
description: "App language", description: "App language",
@@ -1559,6 +1563,9 @@ export const en = {
auto: "System", auto: "System",
}, },
}, },
detailLevel: {
title: "Detail level",
},
fonts: { fonts: {
title: "Fonts", title: "Fonts",
systemDefault: "System default", systemDefault: "System default",
+8
View File
@@ -1511,6 +1511,11 @@ export const es: TranslationResources = {
description: "Líneas mantenidas en el búfer de terminal incorporado", description: "Líneas mantenidas en el búfer de terminal incorporado",
accessibilityLabel: "Líneas del historial de terminal", accessibilityLabel: "Líneas del historial de terminal",
}, },
autoExpandReasoning: {
label: "Siempre expandir razonamiento",
description:
"Mostrar los bloques de pensamiento y razonamiento del agente totalmente expandidos de forma predeterminada",
},
language: { language: {
label: "Idioma", label: "Idioma",
description: "Idioma de la aplicación", description: "Idioma de la aplicación",
@@ -1592,6 +1597,9 @@ export const es: TranslationResources = {
auto: "Sistema", auto: "Sistema",
}, },
}, },
detailLevel: {
title: "Nivel de detalle",
},
fonts: { fonts: {
title: "Fuentes", title: "Fuentes",
systemDefault: "Valor predeterminado del sistema", systemDefault: "Valor predeterminado del sistema",
+7
View File
@@ -1514,6 +1514,10 @@ export const fr: TranslationResources = {
description: "Lignes conservées dans le tampon du terminal intégré", description: "Lignes conservées dans le tampon du terminal intégré",
accessibilityLabel: "Lignes de défilementTerminal", accessibilityLabel: "Lignes de défilementTerminal",
}, },
autoExpandReasoning: {
label: "Toujours afficher le raisonnement",
description: "Afficher le raisonnement de l'agent entièrement développé par défaut",
},
language: { language: {
label: "Langue", label: "Langue",
description: "Langue de l'application", description: "Langue de l'application",
@@ -1596,6 +1600,9 @@ export const fr: TranslationResources = {
auto: "Système", auto: "Système",
}, },
}, },
detailLevel: {
title: "Niveau de détail",
},
fonts: { fonts: {
title: "Polices", title: "Polices",
systemDefault: "Valeur par défaut du système", systemDefault: "Valeur par défaut du système",
+7
View File
@@ -1487,6 +1487,10 @@ export const ja: TranslationResources = {
description: "組み込みターミナルバッファに保持する行数", description: "組み込みターミナルバッファに保持する行数",
accessibilityLabel: "ターミナルスクロールバック行数", accessibilityLabel: "ターミナルスクロールバック行数",
}, },
autoExpandReasoning: {
label: "常に思考プロセスを展開",
description: "デフォルトでAIのエージェント思考・推論ブロックを完全に展開して表示します",
},
language: { language: {
label: "言語", label: "言語",
description: "アプリの言語", description: "アプリの言語",
@@ -1568,6 +1572,9 @@ export const ja: TranslationResources = {
auto: "システム", auto: "システム",
}, },
}, },
detailLevel: {
title: "詳細レベル",
},
fonts: { fonts: {
title: "フォント", title: "フォント",
systemDefault: "システムデフォルト", systemDefault: "システムデフォルト",
+8
View File
@@ -1496,6 +1496,11 @@ export const ptBR: TranslationResources = {
description: "Linhas mantidas no buffer do terminal integrado", description: "Linhas mantidas no buffer do terminal integrado",
accessibilityLabel: "Linhas do scrollback do terminal", accessibilityLabel: "Linhas do scrollback do terminal",
}, },
autoExpandReasoning: {
label: "Sempre expandir raciocínio",
description:
"Mostrar os blocos de pensamento e raciocínio do agente totalmente expandidos por padrão",
},
language: { language: {
label: "Idioma", label: "Idioma",
description: "Idioma do app", description: "Idioma do app",
@@ -1577,6 +1582,9 @@ export const ptBR: TranslationResources = {
auto: "Sistema", auto: "Sistema",
}, },
}, },
detailLevel: {
title: "Nível de detalhe",
},
fonts: { fonts: {
title: "Fontes", title: "Fontes",
systemDefault: "Sistema padrão", systemDefault: "Sistema padrão",
+8
View File
@@ -1501,6 +1501,11 @@ export const ru: TranslationResources = {
description: "Строки, хранящиеся во встроенном буфере терминала.", description: "Строки, хранящиеся во встроенном буфере терминала.",
accessibilityLabel: "Линии прокрутки Terminal", accessibilityLabel: "Линии прокрутки Terminal",
}, },
autoExpandReasoning: {
label: "Всегда разворачивать размышления",
description:
"По умолчанию показывать блоки размышлений и логики агента полностью развернутыми",
},
language: { language: {
label: "Язык", label: "Язык",
description: "Язык приложения", description: "Язык приложения",
@@ -1583,6 +1588,9 @@ export const ru: TranslationResources = {
auto: "Система", auto: "Система",
}, },
}, },
detailLevel: {
title: "Уровень детализации",
},
fonts: { fonts: {
title: "Шрифты", title: "Шрифты",
systemDefault: "Система по умолчанию", systemDefault: "Система по умолчанию",
+7
View File
@@ -1453,6 +1453,10 @@ export const zhCN: TranslationResources = {
description: "内置终端缓冲区保留的行数", description: "内置终端缓冲区保留的行数",
accessibilityLabel: "终端回滚行数", accessibilityLabel: "终端回滚行数",
}, },
autoExpandReasoning: {
label: "始终展开推理过程",
description: "默认情况下完全展开 AI 的思考和推理过程",
},
language: { language: {
label: "语言", label: "语言",
description: "应用语言", description: "应用语言",
@@ -1534,6 +1538,9 @@ export const zhCN: TranslationResources = {
auto: "系统", auto: "系统",
}, },
}, },
detailLevel: {
title: "详细程度",
},
fonts: { fonts: {
title: "字体", title: "字体",
systemDefault: "系统默认", systemDefault: "系统默认",
@@ -16,6 +16,7 @@ import {
DropdownMenuSeparator, DropdownMenuSeparator,
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { Switch } from "@/components/ui/switch";
import { SettingsSection } from "@/screens/settings/settings-section"; import { SettingsSection } from "@/screens/settings/settings-section";
import { import {
MAX_CODE_FONT_SIZE, MAX_CODE_FONT_SIZE,
@@ -189,6 +190,28 @@ function ThemeRow({ value, onChange }: ThemeRowProps) {
); );
} }
interface AutoExpandReasoningRowProps {
value: boolean;
onChange: (value: boolean) => void;
}
function AutoExpandReasoningRow({ value, onChange }: AutoExpandReasoningRowProps) {
const { t } = useTranslation();
return (
<View style={settingsStyles.row}>
<View style={settingsStyles.rowContent}>
<Text style={settingsStyles.rowTitle}>
{t("settings.general.autoExpandReasoning.label")}
</Text>
<Text style={settingsStyles.rowHint}>
{t("settings.general.autoExpandReasoning.description")}
</Text>
</View>
<Switch value={value} onValueChange={onChange} />
</View>
);
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Fonts: family text fields + numeric size fields (commit on blur/submit) // Fonts: family text fields + numeric size fields (commit on blur/submit)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -397,6 +420,13 @@ export function AppearanceSection() {
[updateSettings], [updateSettings],
); );
const handleAutoExpandReasoningChange = useCallback(
(autoExpandReasoning: boolean) => {
void updateSettings({ autoExpandReasoning });
},
[updateSettings],
);
const commitUiFontFamily = useCallback( const commitUiFontFamily = useCallback(
(value: string) => { (value: string) => {
const sanitized = sanitizeFontFamily(value); const sanitized = sanitizeFontFamily(value);
@@ -477,6 +507,14 @@ export function AppearanceSection() {
<ThemeRow value={settings.theme} onChange={handleThemeChange} /> <ThemeRow value={settings.theme} onChange={handleThemeChange} />
</View> </View>
</SettingsSection> </SettingsSection>
<SettingsSection title={t("settings.appearance.detailLevel.title")}>
<View style={settingsStyles.card}>
<AutoExpandReasoningRow
value={settings.autoExpandReasoning}
onChange={handleAutoExpandReasoningChange}
/>
</View>
</SettingsSection>
<SettingsSection title={t("settings.appearance.fonts.title")}> <SettingsSection title={t("settings.appearance.fonts.title")}>
<View style={settingsStyles.card}> <View style={settingsStyles.card}>
{showFontFamilyRows ? ( {showFontFamilyRows ? (