Cherry Studio 消息输入换行改为可配置快捷键:发送 / 换行 / Steer 三角色互斥的设计与迁移指南 人工智能大模型AI 应用交互助手本地部署【免费下载链接】cherry-studio Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址https://gitcode.com/CherryHQ/cherry-studio点击查看免费下载Cherry Studio 从 v2 重构的某次变更PR #186422026-08-15起将聊天、Agent 与绘画三类消息输入框的换行行为从「Enter / ShiftEnter / CmdCtrlEnter 一律插入换行」改为「单一可配置的换行快捷键」并顺势引入Steer转向快捷键用于在 Agent 运行中把草稿直接送入当前轮次。本文以官方 breaking-change 文档为主线结合仓库源码说明新快捷键模型、互斥解析逻辑与底层按键分发实现帮助用户与开发者理解变化并完成迁移。变更概览换行不再是「三键通用」在旧版本中聊天、Agent、绘画消息输入框对Enter、ShiftEnter、Cmd/CtrlEnter一视同仁——任意组合都会插入一个换行符。从 2026-08-15 起变更文档见 v2-refactor-temp/docs/breaking-changes/2026-08-15-composer-mod-enter-no-longer-inserts-line-break.md行为被收敛为换行只由一个可配置快捷键完成默认ShiftEnter配置入口位于Settings Chat Input Line break shortcut发送send、换行line break、Steer 三个角色必须使用不同的按键组合不允许互相占用默认情况下Cmd/CtrlEnter处于空闲状态并成为Steer 快捷键在 Agent 运行时按下它会把当前草稿送入正在进行的这一轮对话而不是排入队列等待。文档同时指出任何既不属于发送、也不属于换行、也不属于 Steer 的 Enter 组合将什么都不做不再退回为插入换行。为什么这对用户有影响这是一次明显的行为破坏breaking change对两类用户影响最大习惯用Cmd/CtrlEnter换行的用户该组合不再插入换行在 Agent 会话中它现在会执行 Steer即把草稿直接注入当前运行轮次。Windows / Linux 用户发送快捷键失去了Win/SuperEnter选项。该组合被操作系统保留在非 macOS 平台上永远不会触发文档称其 was reserved by the OS and could never fire。如果此前选择了这一项迁移后发送将自动回落到CtrlEnter。另外三个快捷键的标签显示也切换到应用的共享按键词表shared key vocabulary例如 macOS 上显示为⌘Enter而非⌘ Enter与其他设置页Settings Shortcuts的写法保持一致。新快捷键模型发送 / 换行 / Steer 三角色互斥新模型把输入框的 Enter 组合划分为三个互斥角色每个角色各占一个组合且不可复用角色默认值macOS默认值Windows / Linux说明Send发送EnterEnter发送当前草稿Line break换行ShiftEnterShiftEnter在输入框中插入换行Steer转向⌘EnterCmdEnterCtrlEnterAgent 运行时把草稿送入当前轮次而非排队三者互斥的规则体现在设置界面中在 ChatPreferenceSections.tsx 中每个下拉框都会隐藏另外两个角色已经占用的按键// Send / newline / steer are mutually exclusive: each select hides the two keys already in use. // Bindings are arrays, so the select trades in their ids and maps back on change. const shortcutItemsExcluding useCallback((...taken: ComposerShortcut[]): SelectOptionstring[] { const takenIds taken.map(composerShortcutId) return COMPOSER_SHORTCUTS.filter((shortcut) !takenIds.includes(composerShortcutId(shortcut))).map( (shortcut) ({ value: composerShortcutId(shortcut), label: getComposerShortcutLabel(shortcut) }) ) }, [])发送下拉排除当前换行与 Steer 组合L211换行下拉排除发送与 SteerL229Steer 下拉排除发送与换行L247从 UI 层面就杜绝了按键冲突。源码级解析快捷键解析与互斥的兜底逻辑互斥不仅停留在 UI 层面存储与解析层同样有兜底。核心实现位于 src/renderer/utils/input.ts可选项集合L85-L91export const COMPOSER_SHORTCUTS: readonly ComposerShortcut[] [ [Enter], [Shift, Enter], [CommandOrControl, Enter], [Alt, Enter], ...(isMac ? [[Ctrl, Enter] as ComposerShortcut] : []) ]注意CommandOrControl在 macOS 上代表 Command⌘在其他平台代表 ControlCtrl因此纯 Ctrl 组合只在 macOS 上才是独立选项macOS 上 ⌘ 与 Ctrl 是两颗不同的键。默认值解析L126-L135export const resolveSendShortcut (stored: unknown): ComposerShortcut resolveComposerShortcut(stored, [], [Enter]) export const resolveNewlineShortcut (stored: unknown, send: ComposerShortcut): ComposerShortcut resolveComposerShortcut(stored, [send], [Shift, Enter]) export const resolveSteerShortcut ( stored: unknown, send: ComposerShortcut, newline: ComposerShortcut ): ComposerShortcut resolveComposerShortcut(stored, [send, newline], [CommandOrControl, Enter])三者各自的偏好preference默认值定义为发送[Enter]、换行与 Steer 均为null表示未覆盖使用生效默认值见 preferenceSchemas.ts。换行与 Steer 存null的设计意味着即使用户修改过发送快捷键未显式覆盖的换行 / Steer 也会随发送键自动漂移到新的空闲组合。互斥兜底resolveComposerShortcut如果存储值被另一角色占用、或首选默认值被占用则回落到第一个空闲组合极端情况下才使用首选值兜底const resolveComposerShortcut ( stored: unknown, taken: readonly ComposerShortcut[], preferred: ComposerShortcut ): ComposerShortcut { const takenIds taken.map(composerShortcutId) const shortcut normalizeComposerShortcut(stored) if (shortcut !takenIds.includes(composerShortcutId(shortcut))) return shortcut if (!takenIds.includes(composerShortcutId(preferred))) return preferred return COMPOSER_SHORTCUTS.find((candidate) !takenIds.includes(composerShortcutId(candidate))) ?? preferred }旧值迁移LEGACY_COMPOSER_SHORTCUTSv1以及 v2 早期存储的是五种固定字符串而非绑定数组迁移映射中CommandEnter当年匹配的是Meta 键即非 macOS 上的 Win/Super 键——这正是文档所说被 OS 保留、永不触发的历史根源。迁移后该组合统一映射为[CommandOrControl, Enter]因此 Windows/Linux 上先前选择它的人现在实际以CtrlEnter发送。源码级解析输入框按键分发与 IME 防护按键的实际分发发生在共享输入框组件 ComposerSurface.tsx。其onKeyDown处理逻辑严格遵循Steer 优先于 Send、其余 Enter 组合一律吞掉的优先级顺序与运行时输入框runtime surface保持一致避免两处逻辑漂移const isEnterPressed (event.key Enter || event.key NumpadEnter) !event.nativeEvent.isComposing if (!isEnterPressed) return event.preventDefault() const isSteerPressed !!props.steerShortcut matchesComposerShortcut(event, props.steerShortcut) if (isSteerPressed || matchesComposerShortcut(event, sendMessageShortcut)) { // Holding the key must not send twice; holding the newline key still repeats. if (event.repeat) return if (props.sendDisabled) { showBlockedSendReason() } else if (isSteerPressed) { void props.onSendDraft(getFallbackDraft(), { steer: true }) } else { void props.onSendDraft(getFallbackDraft()) } return } if (matchesComposerShortcut(event, newlineShortcut)) insertFallbackNewline(event.currentTarget)这段实现中有三个值得注意的工程细节IME 组合防护!event.nativeEvent.isComposing确保中文等输入法组合过程中的 Enter用于选词上屏不会被误判为发送/换行onCompositionStart/End同步维护组合状态L299-L307按住防重复event.repeat使按住发送/Steer 不会重复触发而按住换行键仍可连续插入空行未绑定组合被吞掉既非 Steer、非 Send、也非 Newline 的 Enter 组合在event.preventDefault()之后直接返回不再插入换行——与 breaking-change 文档描述完全一致。按键匹配通过 matchesComposerShortcut 完成它调用共享工具 getShortcutBindingFromKeyboardEvent 将键盘事件归一化为绑定数组含平台差异darwin 下metaKey→CommandOrControl、ctrlKey→Ctrl其他平台ctrlKey→CommandOrControl、metaKey→Meta再与目标快捷键比对。Steer 的语义送入当前轮次而非排队Steer 的核心语义在 AgentComposer.tsx 的handleSendDraft中实现// Busy (streaming) → queue the follow-up; the head auto-drains when the session goes idle and // the dock lets the user steer/edit/remove items. The steer shortcut opts out of the queue and // falls through to the direct send below, mirroring the docks insert action. if (isStreaming !options?.steer) { enqueueFollowup(draft, payload) clearCurrentDraft() return }即Agent 正在流式输出isStreaming时普通发送会把草稿排入后续队列enqueue等待当前轮次空闲后自动消化而携带steer: true的发送则跳过队列直接发送把草稿注入当前运行轮次。这与输入框 Dock 上的insert插入当前轮动作互为镜像——Steer 快捷键就是它的键盘入口。同时 Steer 会保留在 Dock 中并弹出 toast与直接发送/自动排空路径的反馈一致L1747、L1773。用户需要做什么无需任何操作——迁移是自动的ShiftEnter继续作为换行快捷键工作行为与旧版一致若想恢复Cmd/CtrlEnter换行的旧习惯只需在Settings Chat Input Line break shortcut中把它设为换行快捷键设置为换行后Steer 会按互斥规则自动让位到下一个空闲组合若之前在 Windows/Linux 上选择了Win/SuperEnter作为发送键现在将以CtrlEnter发送。相关偏好键速查新快捷键模型对应三个偏好键定义与默认值见 preferenceSchemas.ts偏好键类型默认值说明chat.input.send_message_shortcutComposerShortcut[Enter]发送快捷键chat.input.newline_shortcutComposerShortcut \| nullnull换行快捷键null表示使用生效默认值ShiftEnterchat.input.steer_shortcutComposerShortcut \| nullnullSteer 快捷键null表示使用生效默认值Cmd/CtrlEnter三个角色的互斥约束由 resolveComposerShortcut 在运行时兜底即使偏好数据被外部写入冲突值也不会导致两个角色共用一个按键。赞分享人工智能大模型AI 应用交互助手本地部署【免费下载链接】cherry-studio Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址https://gitcode.com/CherryHQ/cherry-studio点击查看免费下载相关推荐Voyager 发送行为调整指南将 Gemini 发送快捷键改为 CtrlEnter多行提示词输入Voyager 发送行为调整指南将 Gemini 发送快捷键改为 CtrlEnter多行提示词输入 导读 本文讲解 Voyager 扩展的“发送行为SAI 应用前端Voyager 发送行为指南将 Gemini 的 Enter 改为换行、用 CtrlEnter 发送Voyager 发送行为指南将 Gemini 的 Enter 改为换行、用 CtrlEnter 发送 适用版本 Voyager 1.3.7 及后续版本。本AI 应用前端Cherry Studio File Manager v2 迁移执行计划FileMetadata 字段级退役与消费域切换实战指南Cherry Studio File Manager v2 迁移执行计划FileMetadata 字段级退役与消费域切换实战指南 本指南以 Cherry St人工智能大模型AI 应用交互助手本地部署创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考