diff --git a/modules/personalization_manager.py b/modules/personalization_manager.py index e1ac920..b63125e 100644 --- a/modules/personalization_manager.py +++ b/modules/personalization_manager.py @@ -22,6 +22,7 @@ ALLOWED_COMMUNICATION_STYLES = {"default", "human_like", "auto"} ALLOWED_CONVERSATION_CONTINUITY = {"low", "medium", "high"} ALLOWED_GOAL_REVIEW_MODES = {"readonly", "active"} ALLOWED_GOAL_END_CONDITIONS = {"max_turns", "max_tokens"} +ALLOWED_BLOCK_DISPLAY_MODES = {"traditional", "stacked", "minimal"} GOAL_MAX_TURNS_MIN = 1 GOAL_MAX_TURNS_MAX = 100 GOAL_MAX_TURNS_DEFAULT = 5 @@ -94,6 +95,7 @@ DEFAULT_PERSONALIZATION_CONFIG: Dict[str, Any] = { "silent_tool_disable": True, # 禁用工具时不向模型插入提示(默认开启) "enhanced_tool_display": True, # 增强工具显示 "compact_message_display": "full", # 简略消息显示:full-完整原始内容 / brief-一行概要 + "block_display_mode": "stacked", # 堆叠块显示模式:traditional-传统列表 / stacked-堆叠动画 / minimal-极简模式 "show_status_avatar": True, # 是否显示助手状态形象 "stacked_hide_borders": False, # 堆叠块隐藏边线 "show_git_status_bar": True, # 是否显示输入栏上方 Git 状态栏 @@ -452,6 +454,13 @@ def sanitize_personalization_payload( else: base["compact_message_display"] = "full" + # 堆叠块显示模式:traditional(传统列表)/ stacked(堆叠动画)/ minimal(极简模式) + block_display_mode = data.get("block_display_mode", base.get("block_display_mode")) + if isinstance(block_display_mode, str) and block_display_mode.strip().lower() in ALLOWED_BLOCK_DISPLAY_MODES: + base["block_display_mode"] = block_display_mode.strip().lower() + else: + base["block_display_mode"] = "stacked" + # 堆叠块隐藏边线 if "stacked_hide_borders" in data: base["stacked_hide_borders"] = bool(data.get("stacked_hide_borders")) diff --git a/static/src/stores/personalization.ts b/static/src/stores/personalization.ts index 23c3c33..192b276 100644 --- a/static/src/stores/personalization.ts +++ b/static/src/stores/personalization.ts @@ -26,6 +26,7 @@ interface PersonalForm { silent_tool_disable: boolean; enhanced_tool_display: boolean; compact_message_display: CompactMessageDisplay; + block_display_mode: BlockDisplayMode; show_status_avatar: boolean; show_git_status_bar: boolean; auto_open_terminal_panel: boolean; @@ -119,6 +120,28 @@ const loadCachedStackedHideBorders = (): boolean => { return window.localStorage.getItem(STACKED_HIDE_BORDERS_STORAGE_KEY) === 'true'; }; +const loadCachedBlockDisplayMode = (): BlockDisplayMode => { + if (typeof window === 'undefined' || !window.localStorage) { + return 'stacked'; + } + try { + const raw = window.localStorage.getItem(EXPERIMENT_STORAGE_KEY); + if (!raw) { + return 'stacked'; + } + const parsed = JSON.parse(raw); + if ( + typeof parsed?.blockDisplayMode === 'string' && + ['traditional', 'stacked', 'minimal'].includes(parsed.blockDisplayMode) + ) { + return parsed.blockDisplayMode as BlockDisplayMode; + } + } catch (error) { + console.warn('读取堆叠块显示模式缓存失败:', error); + } + return 'stacked'; +}; + const persistStackedHideBorders = (value: boolean) => { if (typeof window === 'undefined' || !window.localStorage) { return; @@ -146,6 +169,7 @@ const defaultForm = (): PersonalForm => ({ silent_tool_disable: false, enhanced_tool_display: true, compact_message_display: 'full', + block_display_mode: loadCachedBlockDisplayMode(), show_status_avatar: true, show_git_status_bar: true, auto_open_terminal_panel: true, @@ -338,6 +362,12 @@ export const usePersonalizationStore = defineStore('personalization', { silent_tool_disable: !!data.silent_tool_disable, enhanced_tool_display: data.enhanced_tool_display !== false, compact_message_display: data.compact_message_display === 'brief' ? 'brief' : 'full', + block_display_mode: + data.block_display_mode === 'traditional' || + data.block_display_mode === 'stacked' || + data.block_display_mode === 'minimal' + ? data.block_display_mode + : 'stacked', show_status_avatar: data.show_status_avatar !== false, show_git_status_bar: data.show_git_status_bar !== false, auto_open_terminal_panel: data.auto_open_terminal_panel !== false, @@ -449,9 +479,15 @@ export const usePersonalizationStore = defineStore('personalization', { this.form = { ...this.form, compact_message_display: 'brief' }; void this.persistCompactMessageDisplay('brief'); } + // 一次性迁移:堆叠块显示模式旧版仅在 localStorage 保存,后端默认 stacked 时回写本地缓存值。 + const cachedBlockMode = this.experiments.blockDisplayMode; + if (this.form.block_display_mode === 'stacked' && cachedBlockMode !== 'stacked') { + this.form = { ...this.form, block_display_mode: cachedBlockMode }; + } this.experiments = { ...this.experiments, - compactMessageDisplay: this.form.compact_message_display + compactMessageDisplay: this.form.compact_message_display, + blockDisplayMode: this.form.block_display_mode }; this.persistExperiments(); this.clearFeedback(); @@ -866,6 +902,10 @@ export const usePersonalizationStore = defineStore('personalization', { blockDisplayMode: mode }; this.persistExperiments(); + this.form = { + ...this.form, + block_display_mode: mode + }; this.scheduleAutoSave(); }, setCompactMessageDisplay(mode: CompactMessageDisplay) {