Skip to content

v1.4.5 | Intermicāns

Latest

Choose a tag to compare

@yuzeguitarist yuzeguitarist released this 09 May 11:59
· 1 commit to main since this release

Deck


Release Notes v1.4.5

SQLite 基准图表 · SQLite benchmark charts

SQLite search latency
搜索延迟 · Search latency

SQLite search speedup
加速比 · Speedup

SQLite query health
查询健康度 · Query health

SQLite run profile
整轮运行概况 · Run profile

TL;DR

  • 剪贴板捕获进入 pboard/XPC 事件驱动时代
    接入 Apple pboard daemon 的私有 invalidation push 链路,复制发生时由 invalidate-cache / invalidate-entries 直接唤醒 Deck 捕获流水线;常驻高频轮询退场,只保留稀疏健康检查与自动回退。
    Clipboard capture now rides the private pboard/XPC invalidation path: invalidate-cache / invalidate-entries wake Deck immediately, while polling becomes a sparse health check and safety fallback.

  • SQLite 搜索性能炸裂治理
    新增 Deck SQLite Benchmark 基准体系后,锁定 FTS5 搜索里 bm25 + timestamp 全量临时排序这一颗大雷;搜索链路改为 rowid DESC 有界候选 + 主表过滤排序,medium 25,000 条数据下最坏多条件搜索从 43.1s 降到 154.6ms,约 278.6x,timeout 从 5/5 清零,整轮 benchmark 从 51.7s 降到 8.7s
    A new Deck SQLite Benchmark suite exposed the FTS5 bm25 + timestamp full-sort trap; search now uses bounded rowid DESC candidates plus table-side filtering/sorting. On the 25k-row medium benchmark, the worst multi-condition search dropped from 43.1s to 154.6ms (278.6x) with 5/5 timeouts eliminated, and the full run fell from 51.7s to 8.7s.

  • DeckClip 连接安全与信道性能
    强化防重放与校验顺序,并提升大数据帧下的读取效率。
    Stronger replay protection and verification ordering, plus larger socket reads for big frames.

  • Deck MCP 进程诊断与清理
    deckclip mcp serve 增加初始化超时保护,mcp doctor 可列出当前 MCP bridge 进程、父进程与运行时长,并新增 mcp cleanup 清理疑似空闲实例。
    deckclip mcp serve now exits if no MCP initialize request arrives, while mcp doctor reports running bridge processes and mcp cleanup can clear likely idle instances.

  • 复制操作反馈更快
    在按下复制/剪切后的短窗口内更快察觉剪贴板变化,音效与状态栏反馈不再拖延;Deck 面板内 Cmd+C 成功复制时也会立即播放同一套反馈音效。
    Faster copy/cut detection with near-immediate sound and menu-bar feedback; successful Cmd+C copies inside the Deck panel now play the same feedback sound immediately.

  • 思考模式对话更稳定
    正确累积、保存并回传 reasoning_content,避免多轮与工具调用时的接口错误。
    Reliable reasoning_content persistence and playback across turns and tool calls.

  • IDE Source Anchor 支持 Sublime Text / Zed
    从 Sublime Text session 与 Zed 剪贴板 zed-metadata 捕获文件和行号,复制源码后可从 Deck 直接跳回对应位置。
    IDE Source Anchor now covers Sublime Text and Zed by reading Sublime session state and Zed zed-metadata, so copied code can jump back to the original file and line.

  • 代码预览高亮更接近编辑器
    代码预览改用轻量单遍 token 扫描与缓存,高亮字符串、注释、关键字、函数、类型、属性、数字等常见语义,同时减少多轮正则扫描开销。
    Code preview now uses lightweight single-pass token scanning with caching, highlighting strings, comments, keywords, functions, types, properties, numbers, and other common semantics, while reducing the overhead of multiple rounds of regex scanning.

  • 面板与长文本预览更流畅
    基于 CPU.trace / UI.trace 的热点优化,减少主线程菜单构建、Markdown 检测与长文本系统探测开销。
    Trace-driven hot-path work reduces main-thread menu construction, Markdown detection, and long-text checking overhead.

  • 面板弹出与收起更自然
    面板动画改为更贴近屏幕边缘的完整滑入/滑出路径,并收紧横版底部氛围栏与卡片间距,减少底部裁切感和空洞感。
    Panel presentation now uses a more natural edge-aligned slide path, with tighter horizontal ambient-bar/card spacing to reduce bottom clipping and empty-space feel.

  • 长文本预览内存暴涨保护
    修复大文本预览触发 TextKit/CoreText 全量排版预热与几何回调复入时,Deck 内存可能异常增长并导致菜单栏面板无响应的问题;超大文本现在使用懒布局路径,并合并尺寸变化触发的重排。
    Long-text previews now avoid eager full-document TextKit/CoreText layout and coalesce geometry-driven relayouts, preventing runaway memory growth and menu-bar unresponsiveness on very large text.

  • 图片预览与缩略图后台解码更稳
    图片预览和列表缩略图加载统一降为后台 utility 优先级,避免高优先级 UI 任务等待默认优先级 ImageIO worker 时触发 priority inversion Hang Risk。
    Image preview and list thumbnail loading now run at utility priority, avoiding priority-inversion Hang Risk reports when high-priority UI tasks wait on default-priority ImageIO workers.

  • 面板关闭后主动回收图片内存
    看过大图后收起面板,Deck 会释放隐藏面板的 SwiftUI 树、图片缩略图、预览大图、PDF 缩略图与链接预览 artwork 缓存;所有内容仍可在下次打开时按原规格重建,不靠削弱功能换内存。
    After image-heavy panel sessions, hiding the panel now releases the hidden SwiftUI tree plus image thumbnails, large preview images, PDF thumbnails, and link-preview artwork caches. Everything is rebuilt at the same quality on the next open, without feature cuts.

  • 图片粘贴与拖拽兼容性修复
    修复 Claude Code 终端图片粘贴与剪映截图拖入的两个兼容性问题:图片自动粘贴会按目标宿主选择更安全的快捷键,图片拖拽会提供 Deck 管理的临时文件表示,避免接收 App 报无访问权限。
    Image paste and drag compatibility is improved for Claude Code terminal workflows and Jianying screenshot imports: Deck now selects the safer paste shortcut per target host and exports image drags through Deck-managed temporary file representations.

  • 几百个文件的预览不再拖垮 CPU
    基于 PreviewCPU.trace / aitrace 定位多文件预览切换条热点,预览时改为按水平可视区域懒加载文件入口,避免一次性渲染几百个文件名与图标。
    PreviewCPU.trace / aitrace guided a multi-file preview fix: Deck now lazily builds file entries from the horizontal viewport instead of rendering hundreds of file chips and icons at once.

  • 恢复备份与安全模式更可靠
    修复恢复备份、删除全部记录、安全模式切换、FTS/vec 索引与外部 Blob 引用之间的多处边界问题。
    Recovery backups are more reliable across delete-all flows, security-mode toggles, FTS/vector indexes, and external Blob references.

优化 / Improvements

  • Deck SQLite Benchmark 基准体系
    建立独立 SQLite benchmark,复刻 Deck 真实主表、复合索引、FTS5 trigram、触发器、WAL/PRAGMA、列表轻量投影,以及 startup / panel / search / write / maintenance 五类核心场景;结果输出 JSON + CSV,并记录 EXPLAIN QUERY PLAN、index/full-scan/temp B-tree、timeout、吞吐、DB/WAL/Blob 体积等结构化指标。medium 档固定为 25,000 条混合文本、代码、URL、图片、文件与富文本记录,可用 36 条 read-only 连接并发压测读路径,后续数据库改动不再靠体感判断。
    Added a standalone SQLite benchmark that mirrors Deck’s real table, composite indexes, FTS5 trigram setup, triggers, WAL/PRAGMAs, lightweight list projection, and startup / panel / search / write / maintenance scenarios. Results are emitted as JSON + CSV with EXPLAIN QUERY PLAN, index/full-scan/temp-B-tree flags, timeouts, throughput, and DB/WAL/Blob storage snapshots. The medium scale uses 25,000 mixed text/code/URL/image/file/rich-text rows and can drive read paths through 36 read-only connections, so database changes are now measured instead of guessed.

  • FTS5 搜索 SQL 治理
    搜索 SQL 不再对 FTS 大命中集执行 ORDER BY bm25(ClipboardHistory_fts), timestamp DESC, id DESC 全量打分与临时排序;无结构过滤时直接从 FTS virtual table 取 rowid DESC LIMIT,带类型/标签过滤时先生成有限 FTS 候选,再 join ClipboardHistory 走主表索引过滤与时间排序。medium benchmark 下,普通关键词搜索 1105.0ms → 60.0ms(18.4x),日期过滤 1125.4ms → 85.8ms(13.1x),类型过滤 452.6ms → 111.8ms(4.0x),App 过滤 825.2ms → 169.5ms(4.9x),最坏多条件组合 43086.4ms → 154.6ms(278.6x)。这条路径同时减少临时 B-tree、长时间 CPU 空转与并发读竞争,速度、性能和能耗一起收敛。
    FTS5 search no longer fully scores and temp-sorts large match sets with ORDER BY bm25(ClipboardHistory_fts), timestamp DESC, id DESC. Plain searches now pull bounded rowid DESC LIMIT results directly from the virtual table; filtered searches materialize a finite FTS candidate set and then let ClipboardHistory indexes handle type/tag filtering and recency ordering. On the medium benchmark, keyword search improved 1105.0ms → 60.0ms (18.4x), date-filtered search 1125.4ms → 85.8ms (13.1x), type-filtered search 452.6ms → 111.8ms (4.0x), app-filtered search 825.2ms → 169.5ms (4.9x), and the worst multi-condition combo 43086.4ms → 154.6ms (278.6x). This cuts temp B-trees, long CPU spins, and read-contention energy at the same time.

  • 私有 pboard/XPC Invalidation Bridge
    新增运行时私有事件桥:启动时连接 com.apple.pasteboard.1,完成 com.apple.pboard.createget-countsrefresh-cache 后订阅系统级剪贴板 invalidation;一旦收到 invalidate-cache / invalidate-entries,立即触发 Deck 原有捕获 pipeline。
    Added a runtime pboard/XPC invalidation bridge: Deck connects to com.apple.pasteboard.1, performs create / get-counts / refresh-cache, and wakes the existing capture pipeline as soon as private invalidation pushes arrive.

  • 事件驱动后的低功耗健康检查
    私有事件在当前 GUI session 中验证成功后,轮询从主触发机制降级为 30s 稀疏 watchdog;既保留复制响应速度,又显著减少后台无意义唤醒。
    Once the private event path is validated in the active GUI session, polling is downgraded to a 30s sparse watchdog, preserving responsiveness while cutting idle wakeups.

  • Unix Socket 读缓冲
    将读缓冲由 8KiB 提升到 64KiB,与核心侧一致,减轻大消息读取时的系统调用压力。
    Read buffer raised from 8KiB to 64KiB (aligned with core) to reduce syscall overhead for large payloads.

  • Rust CLI 聊天流解析
    聊天帧在协议层一次性结构化解析,避免多余中间表示,路径更直接、更易维护。
    Chat stream frames deserialize once at the protocol layer instead of round-tripping through generic JSON values.

  • Deck MCP bridge 启动防残留
    deckclip mcp serve 启动后若 60 秒内没有收到 MCP initialize,会主动退出,避免外部 MCP host 启动失败或握手中断后留下空转 stdio 进程;已初始化的正常会话不会被普通 idle timeout 打断。可通过 DECKCLIP_MCP_INITIALIZE_TIMEOUT_SECONDS=0 关闭该保护。
    deckclip mcp serve now exits if no MCP initialize request arrives within 60 seconds, preventing stale stdio bridge processes after host startup/handshake failures. Initialized sessions are not interrupted by a generic idle timeout, and the guard can be disabled with DECKCLIP_MCP_INITIALIZE_TIMEOUT_SECONDS=0.

  • Deck MCP doctor / cleanup
    deckclip mcp doctor 新增运行中 deckclip mcp serve 诊断,输出数量、PID、PPID、父进程名、运行时长与启动命令;新增 deckclip mcp cleanup --dry-run --idle-hours <hours> 预览清理,确认后可移除超过阈值的疑似空闲 bridge 进程。
    deckclip mcp doctor now reports running deckclip mcp serve processes with count, PID, PPID, parent process, elapsed time, and command. deckclip mcp cleanup --dry-run --idle-hours <hours> previews cleanup candidates before removing likely idle bridge processes.

  • 剪贴板触发策略升级
    优先使用 pboard/XPC invalidation 事件;事件链路未验证、断开或系统生命周期切换期间,自动回退到低能耗自适应轮询与复制快捷键短探测窗口,稳定性与省电同时兜住。
    Prefers pboard/XPC invalidation events; before validation, after disconnects, or during system lifecycle transitions, Deck automatically falls back to adaptive polling plus short copy-shortcut probes.

  • 私有事件验证 warmup
    pboard/XPC 首次确认可用后,先进入 120 秒、5 秒间隔的健康观察窗口,再降级到 30 秒稀疏 watchdog;避免「首次事件成功、后续投递静默失效」时过早进入低频检查。
    After the pboard/XPC path is first validated, Deck keeps a 120-second warmup window with 5-second health checks before relaxing to the 30-second sparse watchdog, preventing premature low-frequency checks if delivery silently stops after the first event.

  • pboard 重新订阅合并
    同一次复制常见的 invalidate-cache + invalidate-entries 不再重复刷新订阅:同 generation 已刷新则跳过,刷新进行中则记录 pending generation,完成后只在确有更新时补跑。
    Resubscribe work is coalesced for paired invalidate-cache / invalidate-entries pushes: same-generation refreshes are skipped, in-flight requests record a pending generation, and only genuinely newer generations trigger a follow-up refresh.

  • Markdown 智能检测热路径
    表格分隔线与水平分隔线检测改为轻量字符扫描,移除高频正则与字符串替换,降低文本分析时的 CPU 与分配压力。
    Markdown table-separator and horizontal-rule checks now use lightweight character scans instead of hot regex/string-replacement paths.

  • 长文本预览系统检测开销
    长文本 NSTextView 关闭自动数据探测、拼写、语法与文本替换检查,保留 Cmd+F,同时避免 DataDetectors 在 UI 路径中反复折叠/扫描字符串。
    Long-text preview disables automatic data/spell/grammar/text replacement checks while keeping Cmd+F, avoiding DataDetectors string-folding work on the UI path.

  • 图片解码 QoS 收敛
    PreviewOverlayView 的大图预览解码与 ClipItemRowView 的列表缩略图任务改为 utility QoS;保留原有 downsample / cache / fallback 流程,只调整任务优先级,降低 Instruments Hang Risk 中的 QoS 反转噪音。
    Large image decoding in PreviewOverlayView and list thumbnail work in ClipItemRowView now use utility QoS; the existing downsample/cache/fallback behavior is unchanged, with only task priority adjusted to reduce QoS inversion noise in Instruments Hang Risk.

  • ImageIO 临时内存收敛
    图片卡片缩略图、列表预览缩略图与写入时预生成缩略图的 ImageIO 路径补充局部 autorelease pool,并显式禁止 source 级缓存;保留即时 downsample 与现有尺寸/格式兜底策略,减少大图解码后的临时对象和脏页滞留。
    ImageIO paths for card thumbnails, list/preview thumbnails, and write-time preview generation now use local autorelease pools and disable source-level caching while preserving immediate downsampling plus the existing size/format fallbacks, reducing transient object and dirty-page retention after large image decodes.

  • 面板隐藏态视觉缓存释放
    面板收起并保持关闭后,Deck 会卸载隐藏的 NSHostingView<DeckContentView>,并清理可重建的 CGImage / NSImage 视觉缓存:卡片缩略图、预览大图、PDF 首页缩略图、base64 图片缩略图、Link Preview favicon/hero image 等都会在后台态释放,下次打开按原流程重新加载。
    Once the panel remains hidden, Deck unloads the hidden NSHostingView<DeckContentView> and clears rebuildable CGImage / NSImage visual caches, including card thumbnails, large preview images, PDF first-page thumbnails, base64 image thumbnails, and Link Preview favicon/hero images. The next panel open reloads them through the same behavior path.

  • 多文件预览切换条限流
    几十到几百个文件一起复制时,空格预览仍可逐个前后切换并保持准确计数;顶部切换条改用 viewport 驱动的 LazyHStack,只实例化当前水平可见区域附近的文件 chip,箭头切换仅负责滚动定位,不再决定渲染窗口。
    For copied batches with dozens or hundreds of files, the space preview keeps exact counts and next/previous navigation; the switcher now uses a viewport-driven LazyHStack so only horizontally visible file chips are instantiated, while arrow navigation only scrolls the selected file into view instead of defining the render window.

  • 卡片右键菜单构建
    缓存高频菜单项的本地化字符串,避免每次构建 ClipItemCardView 右键菜单时重复查找 bundle localized string。
    Frequently used context-menu labels are cached to avoid repeated bundle localization lookups during ClipItemCardView menu construction.

  • aitrace 四 Trace 面板热路径优化
    基于 DeckGPU.traceDeckLaunch&Pannel.traceDeckOpenPannelDisk.traceSwiftAnimation.traceaitrace 取证,收敛 SwiftUI 主线程更新、SmartText 电话检测、右键菜单与首次脚本/模版库加载热路径;电话检测结果缓存并预编译正则,模版库菜单只读取轻量库元数据,脚本插件扫描延后到后台预热,deck://paste 参数查找改为一次性索引,保持功能行为不变同时降低面板打开、动画与菜单构建时的 CPU / I/O 抖动。
    aitrace evidence from DeckGPU.trace, DeckLaunch&Pannel.trace, DeckOpenPannelDisk.trace, and SwiftAnimation.trace guided a focused panel hot-path pass: phone detection now caches results and uses precompiled regexes, template-library menus read lightweight library metadata only, script-plugin scanning is warmed off the interaction path, and deck://paste query lookup is indexed once, preserving behavior while reducing CPU and I/O churn during panel opening, animation, and context-menu construction.

  • 面板滑入/滑出动画调优
    面板内容现在在透明动画宿主内完成滑动,横版底部与竖版侧边都保留真实屏幕留白,同时让可见圆角面板完整进入和离开;动画时长与 cubic timing curve 也进一步收紧,减少拖沓感。横版底部氛围栏高度和偏移同步下调,卡片尺寸计算略微补偿,使底部视觉更紧凑。
    Panel content now slides inside a transparent animation host, preserving the visible screen inset in both horizontal and vertical layouts while allowing the rounded panel to enter and leave as a complete surface. Durations and cubic timing curves were tightened for a snappier feel. The horizontal ambient bar is also shorter and closer to the cards, with a small card-size compensation to keep the bottom area visually compact.

  • 横板卡片层次感微调
    横板模式卡片增加更轻的外阴影,保留顶部信息区原有背景层次;队列模式下的横板卡片角标改为右上角黄色 #序号,减少暗色模式下的高亮圆点干扰;竖板模式保持不变。
    Horizontal cards now use a subtler outer shadow that preserves the header background hierarchy; queue-mode horizontal cards now show a yellow #number marker in the top-right instead of a bright circular badge, while vertical cards remain unchanged.

  • 搜索框凹陷层次微调
    Search Clipboard 输入框改为更轻的半透明内凹底色,并用浅色灰描边、深色白描边叠加克制的内侧明暗过渡,让搜索区域从 Liquid Glass 表面轻微下沉但不出现厚重高亮边。
    The Search Clipboard field now uses a lighter translucent recessed fill, with a gray stroke in Light Mode, a white stroke in Dark Mode, and restrained inner light/shade transitions so the search area sits subtly below the Liquid Glass surface without a heavy focus ring.

  • 横板卡片删除动画
    横板模式删除卡片时改为两段式收起:卡片内容先轻微模糊、淡出并缩小,再延迟收窄卡片宽度,让相邻卡片自然补位;竖板模式保持原有行为。
    Horizontal card deletion now uses a two-stage exit: the card content blurs, fades, and scales down first, then its slot collapses so neighboring cards slide into place naturally. Vertical layout keeps the existing behavior.

  • aitrace 三 Trace 能耗优化
    基于 DeckUIMonitorTrace.traceDeckURLNet.traceTimeProfile.traceaitrace 取证,新增一组以低回归为前提的能耗补丁:MultipeerService 只在真正连接、邀请或发送时懒创建 MCSession,空闲时仅释放 session 本身而不触碰 advertiser/browser,减少 MultipeerConnectivity 的常驻 send/recv worker 能耗;复制提示音在播放后自动释放 AVAudioPlayer,避免 AudioSession 长驻;LAN 发送菜单与脚本插件菜单改为轻量 snapshot,降低列表/右键菜单的 SwiftUI fanout;SmartTextService 的 JWT 检测改为单遍字节扫描,减少滚动与智能分析时的 regex 开销;同时补充并通过了最小 LAN lifecycle regression test 与现有 Multipeer stress experiment,确认 idle session release 不会重新 stop/start 整套 LAN discovery 生命周期。
    aitrace evidence from DeckUIMonitorTrace.trace, DeckURLNet.trace, and TimeProfile.trace drove a low-regression energy pass: MultipeerService now lazily creates MCSession only for real connect/invite/send paths and releases only the idle session (not the advertiser/browser), cutting persistent MultipeerConnectivity send/recv worker cost; copy feedback releases AVAudioPlayer after playback so AudioSession workers do not stay resident; LAN-send and script-plugin menus use lightweight snapshots to reduce SwiftUI fanout; SmartTextService JWT detection now uses a single-pass byte scanner instead of heavier regex work; and the change was backed by a new minimal LAN lifecycle regression test plus the existing Multipeer stress experiment to confirm idle session release does not reintroduce discovery-object churn.

  • DeckCPU.trace 搜索与 Markdown 热路径优化
    基于 DeckCPU.trace / aitrace 0.2.0 的 CPU 与 thread-state 取证,确认当前 CPU 低利用率主要来自线程等待与主线程短时 SwiftUI diff/layout burst,而可无损收敛的代码热区集中在 SearchService.exactSearchIds 的 Swift Substring 索引路径和 SmartTextService.detectMarkdownSignals 的普通文本 split/regex 入口。精确搜索的 ID 排序路径改用 NSString.range(of:options:) 做 case/diacritic insensitive 存在性判断,避免不需要高亮范围时构造 Swift Range<String.Index>;Markdown 检测增加语法标记早退,普通文本不再进入逐行 split 与后续正则检测。功能、排序、匹配语义与 Markdown 能力保持不变。
    DeckCPU.trace / aitrace 0.2.0 showed that the low real CPU utilization mostly came from thread waits plus short main-thread SwiftUI diff/layout bursts, while the safe code-level wins were SearchService.exactSearchIds spending time in Swift Substring indexing and SmartTextService.detectMarkdownSignals entering split/regex work for plain text. Exact-search ID ordering now uses NSString.range(of:options:) for case/diacritic-insensitive existence checks, avoiding Swift Range<String.Index> construction when highlight ranges are not needed; Markdown detection now exits early when no Markdown syntax marker exists, keeping plain text out of line-splitting and regex paths. Functionality, ordering, match semantics, and Markdown capabilities remain unchanged.

  • IDE Source Anchor:Sublime Text 与 Zed
    Sublime Text 复制时读取 Auto Save Session.sublime_session / Session.sublime_session 中的 selected sheet 与 selection;Zed 复制时直接解析剪贴板私有 zed-metadatafile_path 与 0-based line_range,统一写入 Deck 的 source_anchor
    Sublime Text copies now resolve selected sheet/selection from Auto Save Session.sublime_session / Session.sublime_session; Zed copies parse private zed-metadata (file_path plus 0-based line_range) and persist it as Deck source_anchor.

  • 源码位置回跳打开方式
    Source Anchor 打开时优先使用对应 IDE CLI(subl / zed),并保留 URL scheme 或系统打开作为兜底;从 Deck 预览页点击即可回到原文件行号。
    Source Anchor opening prefers the matching IDE CLI (subl / zed) with URL/system-open fallbacks, letting preview clicks return to the original source line.

  • 代码预览语法高亮管线
    将旧的关键字/字符串/数字/注释多轮正则替换为轻量 capture 风格扫描器:注释和字符串先形成互斥 token,避免在字符串或注释里误染关键字;再按语言识别声明名、调用、类型名、属性、JSON/YAML key、HTML/XML tag/attribute、Shell 变量等常见结构。
    Replaced the old keyword/string/number/comment regex passes with a lightweight capture-style scanner: comments and strings are isolated first, then language-aware passes color declarations, calls, types, properties, JSON/YAML keys, HTML/XML tags/attributes, Shell variables, and common structural tokens.

  • iOS 同步快捷指令上传提速
    快捷指令仍保留「上传剪贴板 / 下载剪贴板」两个入口,但上传不再在 iPhone 端反复强转并计数剪贴板类型;统一走二进制上传入口,由 Mac 端判定文本、图片或文件,减少 Shortcuts 动作链开销与传文件时的 frame-stream 中断概率。
    The iOS shortcut still exposes only “Upload Clipboard” and “Download Clipboard”, but uploads no longer repeatedly coerce and count clipboard item types on the iPhone. All uploads use the binary endpoint, with the Mac classifying text, images, and files, reducing Shortcuts overhead and frame-stream interruptions during file transfers.

  • iOS 同步服务端响应路径
    iOS 上传写入数据库成功后立即响应,面板刷新、最近同步时间、自动粘贴与 iCloud 同步改为后台收尾;非 multipart 文件上传优先移动临时文件而不是重新复制一份,降低大文件上传延迟。
    The Mac now responds to iOS uploads as soon as the database insert succeeds; panel refresh, last-sync time, paste, and iCloud sync finish in the background. Non-multipart file uploads prefer moving the temporary upload file instead of copying it again, reducing large-file latency.

  • iOS 下载最近内容查询
    下载端查找最近可同步内容时改为逐行命中即停,不再每批先映射完整 500 条历史记录,降低大历史库或加密模式下的解密与对象构建开销。
    Download lookup now stops as soon as a pullable row is found instead of mapping a full 500-row batch first, reducing decryption and object-construction work for large histories or security mode.

修复 / Fixes

  • 剪贴板事件桥锁屏/解锁稳定性
    针对锁屏、熄屏、睡眠、唤醒与 pboard daemon 生命周期变化新增 suspend / resume / bootstrap 流程;connection invalid 不再被当作普通运行时崩坏,而是清理旧 uuid/connection 后走 graceful retry。
    The private clipboard bridge now handles lock screen, display sleep, system sleep, wake, and pboard daemon lifecycle transitions with suspend / resume / bootstrap; connection invalid is treated as a graceful retry path after cleaning stale uuid/connection state.

  • Sleep/Wake 后 pboard refresh-cache 协议错误恢复
    针对唤醒后 refresh-cache 携带旧 change token 返回 com.apple.pboard.error = -22 的情况,Deck 会保留已成功完成的 get-counts 订阅,并自动不带 change 重试一次 refresh-cache,避免一次协议抖动让事件桥退化。
    After wake, if refresh-cache rejects a stale change token with com.apple.pboard.error = -22, Deck now keeps the successful get-counts subscription and retries refresh-cache once without the stale token instead of degrading the bridge.

  • pboard generation 单调状态保护
    修复 watchdog / 重新订阅期间 get-counts 已前进到新 generation、但随后 refresh-cache 返回旧 generation metadata 时,内部状态被回退的问题;Deck 现在以 generation 作为稳定顺序信号,只接受不倒退的 pboard 状态。
    Fixed a resubscribe race where get-counts could advance to a newer generation while a following refresh-cache returned stale metadata; Deck now treats generation as the ordering signal and ignores backward pboard state updates.

  • 剪贴板事件 watchdog 误杀收敛
    Watchdog 不再因一次 missed change 立刻禁用私有事件桥;先执行 fallback poll 并请求 get-counts / refresh-cache 重新订阅,连续多次 miss 后才回退重启,避免健康检查和事件驱动抢状态。
    The watchdog no longer kills the private event bridge after a single missed change; it first performs fallback polling and requests get-counts / refresh-cache resubscription, only restarting after repeated misses.

  • pboard async invalidation 处理链路
    com.apple.pboard.invalidate-cachecom.apple.pboard.invalidate-entriesflush-entries 统一进入私有事件回调,Swift 侧验证后切到 event-driven 模式,并在 debounce 确认 changeCount 变化后触发捕获。
    invalidate-cache, invalidate-entries, and flush-entries now flow through one private event callback; Swift validates delivery, switches to event-driven mode, and triggers capture after debounce-confirmed changeCount movement.

  • 私有事件 debounce 稳定性
    pboard event 到达后不再只采样一次 12ms debounce;现在会在 12ms / 35ms / 75ms 的有限事件触发窗口内等待公开 NSPasteboard.changeCount 追上,改善唤醒、promised metadata 或 daemon 状态抖动时的捕获稳定性,同时不恢复常驻高频轮询。
    Private event debounce now uses a bounded 12ms / 35ms / 75ms event-triggered settle window instead of a single 12ms sample, giving NSPasteboard.changeCount time to catch up after wake, promised metadata, or daemon churn without returning to steady high-frequency polling.

  • 私有事件桥 false validation 防护
    仅「收到 pboard event」不再足以切到 30 秒健康检查;必须在 debounce 后证明该事件对应一次有效 changeCount 变化。若 probing 阶段连续 3 次真实剪贴板变化都只能靠 fallback polling 捕获,Deck 会禁用私有事件桥并停留在普通自适应轮询,避免旧系统或协议不兼容时误入 30 秒兜底。
    Receiving a pboard event alone no longer validates the private bridge; debounce must prove that the event maps to an effective changeCount movement. If three real changes during probing are captured only by fallback polling, Deck disables the private bridge and stays on normal adaptive polling so older macOS versions or incompatible protocol behavior cannot fall into a 30-second fallback path.

  • DeckClip Nonce 防重放
    连接内 nonce 与时间戳关联并按时间窗淘汰;容量上限时丢弃最旧项,不再在计数触顶时整表清空导致旧 nonce 可被重放。
    Nonces map to timestamps with time-window eviction; overflow trims oldest entries instead of clearing the cache, closing a replay window.

  • Nonce 写入与安全校验顺序
    仅在 HMAC 校验通过后才记录 nonce,避免无效请求污染防重放缓存。
    Nonces are recorded only after HMAC verification so bogus requests cannot fill the replay cache.

  • 复制音效与状态栏反馈延迟
    在确认剪贴板已变化后立即触发音效与状态栏更新,不再等待后续解析、规则处理或入库完成。
    Sound and status feedback fire as soon as a clipboard change is confirmed, not after parsing, rules, or persistence.

  • 面板内 Cmd+C 复制音效缺失
    Deck 面板内执行 Cmd+C 复制选中记录或可复制文本时,复制成功后直接触发本地复制反馈;不再依赖系统 pasteboard 事件回流,避免内部写入被跳过时只出现「Updated 1 item」而没有声音。
    Cmd+C inside the Deck panel now triggers local copy feedback immediately after a successful copy, so Deck-owned pasteboard writes no longer produce an update-only response with no sound.

  • 粘贴入口编译警告清理
    Shortcuts/AppIntent 与 Orbit CLI bridge 的粘贴入口显式处理 ClipboardService.paste(...) 返回值,清理 Swift MainActor.run unused-result 警告。
    Shortcuts/AppIntent and Orbit CLI bridge paste paths now explicitly discard the ClipboardService.paste(...) return value, clearing Swift MainActor.run unused-result warnings.

  • 思考模式 reasoning_content 的传递
    在流式与非流式响应中累积 reasoning_content、写入助手消息持久化内容,并在请求 /chat/completions 时原样回传,避免「须将 reasoning 传回」类错误。
    Accumulates reasoning_content from streaming and non-streaming replies, persists it on assistant messages, and sends it back to the API verbatim to avoid thinking-mode HTTP 400s.

  • 含工具调用的助手消息
    带有 tool_calls 的助手消息在发往模型时同样携带 reasoning_content,支持同一会话内多轮工具调用。
    Assistant messages that include tool_calls also carry reasoning_content on outbound API calls for multi-turn tool use.

  • YAML 与 Markdown 判定边界
    当 YAML 结构证据明显强于 Markdown 弱信号时不再被 --- 或列表项误判为 Markdown,保留 YAML 代码识别结果。
    YAML with stronger structured-data evidence is no longer misclassified as Markdown because of --- or list-like weak Markdown signals.

  • 长文本预览内存异常增长
    修复大文本 NSTextView 在尺寸变化时反复触发 prewarmScrollableLayoutensureLayoutusedRect 全量布局,导致 TextKit/CoreText 缓存和 physical footprint 异常放大的问题;超大文本改为非连续懒布局,并防止 clip view 几何回调重入。
    Fixed runaway memory growth in long-text previews where clip-view geometry changes repeatedly drove full prewarmScrollableLayout, ensureLayout, and usedRect work, expanding TextKit/CoreText caches and physical footprint. Very large text now uses guarded non-contiguous lazy layout.

  • 精确搜索结果按复制时间稳定排序
    精确搜索改为真正的字面量匹配:所有命中内容按复制时间从新到旧排列,避免 FTS 相关度或标题置顶把旧记录排到前面;同分模糊搜索也使用稳定的分数优先、时间兜底排序。
    Exact search now uses literal matching with newest-copied results first, preventing FTS relevance or title boosting from surfacing older equal matches; equal-score fuzzy hits also keep a stable score-first, recency-tiebreak order.

  • 标签删除不再误删剪贴板记录
    删除自定义标签现在只会把对应记录移回未分组,不再删除该标签下的剪贴板内容、外部 Blob 或同步数据;同时修复无关键词规则过滤的分页截断、AI Chat 快速连发时旧流清理新状态,以及直接粘贴在面板收起前过早触发的问题。
    Deleting a custom tag now moves its items back to the ungrouped state instead of deleting clipboard records, external blobs, or synced data. This also fixes no-keyword rule-filter pagination truncation, stale AI Chat streams clearing newer state, and direct paste firing before the panel fully dismisses.

  • 恢复备份后开启安全模式失败
    修复「创建恢复备份 → 删除全部记录 → 从备份恢复 → 开启安全模式」时,SQLite 连接、sqlite-vec 扩展、FTS 触发器或缺失 Blob 引用导致迁移失败的问题。
    Fixed security-mode migration failures after creating a recovery backup, deleting all items, restoring the backup, and enabling security mode.

  • 恢复失败后的存储重新初始化
    从恢复备份还原失败时也会重新初始化存储层,避免 SQL handle 已关闭但界面继续使用旧状态。
    Storage is reinitialized even after failed recovery-restore attempts so disconnected SQL handles do not linger until restart.

  • 恢复备份 DB/Blob 快照一致性
    数据库备份与 Blobs 快照以成对方式提交;若 DB 指向外部 Blob 但文件已缺失,将跳过本次备份,避免覆盖出新的不完整恢复点。
    Database and Blobs recovery snapshots are committed as a pair; backups are skipped when referenced external Blob files are already missing.

  • 恢复后的 FTS 与 vec 索引状态
    还原恢复备份后会重建 FTS;删除全部记录或安全模式迁移前会清理可能损坏的 FTS/vec 触发器,失败分支也会恢复可用索引。
    FTS is rebuilt after recovery restore, and stale FTS/vec triggers are cleaned around delete-all and security-migration paths with failure recovery.

  • 缺失外部 Blob 引用收敛
    旧版 DB-only 恢复备份中已经无法找回的 blob_path 会在恢复后或安全模式迁移中清除,避免后续备份持续跳过或反复打印缺失 Blob 警告。
    Stale blob_path references from legacy DB-only backups are cleared after restore or during security migration to stop repeated missing-Blob warnings.

  • Deck 自有来源图标
    修复 iOS Sync、Deck WLAN 与 LAN Sharing 等 Deck 自己生成或接收的历史记录在卡片左上角显示为空白或普通文件图标的问题;这些来源现在统一使用 Deck App 图标,列表、卡片与预览信息栏保持一致。
    Deck-owned sources such as iOS Sync, Deck WLAN, and LAN Sharing now use the Deck app icon instead of falling back to a blank or generic document icon across rows, cards, and preview metadata.

  • Claude Code / Ghostty 图片粘贴识别
    修复 Claude Code 在 Ghostty 中窗口标题不包含 Claude Code、只显示类似 jerry · 838ff463-eae1-45 会导致 Deck 误发 Command+V、最终只输入一个 v 的问题;Deck 现在会用 Claude Code session id 前缀匹配 ~/.claude/session-env,确认目标会话后才切到 Ctrl+V 图片粘贴路径。
    Fixed Claude Code image paste in Ghostty when the window title does not contain Claude Code and only shows a title like jerry · 838ff463-eae1-45: Deck now matches the Claude Code session-id prefix against ~/.claude/session-env before switching to the Ctrl+V image-paste path, preventing the previous Command+V fallback from entering a stray v.

  • 剪映截图拖入权限错误
    图片卡片和竖版行视图的拖拽 provider 统一收敛到 ClipboardItem,截图/图片拖拽会先物化为 Deck 管理的临时副本并通过 NSItemProvider 文件表示交给接收 App,减少剪映等严格沙盒导入路径上的「无访问权限」错误。
    Image drag providers for cards and vertical rows now share the ClipboardItem implementation; screenshots/images are materialized as Deck-managed temporary copies and exposed through NSItemProvider file representations to reduce permission errors in stricter sandboxed importers such as Jianying.

说明 / Notes

  • Biome transport 已移除
    逆向验证中 BiomeLibrary / BiomeStreams / BMBiomeScheduler / BPSSink 虽可创建,但第三方 Deck 进程收不到 Pasteboard.Change input;本版删除该诊断 transport,避免 bookmark / completion 噪音影响状态机,主路径只保留已验证的 pboard/XPC invalidation。
    The Biome diagnostic transport has been removed: although BiomeLibrary / BiomeStreams / BMBiomeScheduler / BPSSink could be created, third-party Deck processes did not receive Pasteboard.Change inputs; the verified pboard/XPC invalidation path is now the only private transport.

  • 私有 API 运行时加载与失败回退
    私有 pboard/XPC 链路只作为触发信号使用,真实剪贴板内容仍通过 NSPasteboard 读取;若启动检测、运行中连接、系统恢复或重新订阅任何一步失败,Deck 会恢复普通剪贴板工具级别的自适应轮询。
    The private pboard/XPC path is used only as a trigger; actual clipboard data still comes from NSPasteboard. If startup validation, runtime connection, lifecycle recovery, or resubscription fails, Deck restores standard adaptive polling.

  • 签名字符串与 HMAC 测试向量
    增加跨语言共享的 canonical JSON / HMAC 向量,Rust 集成测试与 Swift 单测对齐签名与序列化结果;应用侧提供仅供测试使用的规范化 JSON 入口以固定行为。
    Shared canonical JSON/HMAC vectors keep Rust integration tests and Swift unit tests aligned; the app exposes a test-only canonical JSON helper to lock signing behavior.

  • Rust 代码风格检查
    源码排版已与 cargo fmt / rustfmt --check 预期一致,避免无意义的格式差异。
    Rust sources are formatted to pass cargo fmt / rustfmt --check without spurious drift.

  • Trace 覆盖范围
    本轮基于 CPU.traceUI.traceMemory.trace 做定位;Memory.trace 未暴露可操作的应用内存栈,因此只落地有 trace 证据支撑的低风险 CPU/UI 改动。
    This pass used CPU.trace, UI.trace, and Memory.trace; because Memory.trace did not expose actionable app memory stacks, only trace-backed low-risk CPU/UI changes were shipped.

  • 旧恢复备份中的外部 Blob
    旧版本只包含 Deck.sqlite3.bak、不包含 .bak.blobs 的恢复备份无法恢复已经被删除的外部大文件;升级后会清理这些失效引用,并保留可用的元数据与预览信息。
    Legacy DB-only recovery backups cannot restore external large payloads after those files are gone; the app now cleans invalid references while keeping usable metadata and previews.

兼容性与行为说明 / Compatibility & Behavior Notes

  • 剪贴板私有事件不可用时的行为
    如果当前 macOS 版本、会话状态或 pboard daemon 生命周期导致私有 invalidation 链路不可用,Deck 会自动保留或恢复自适应轮询;功能正确性不依赖私有 API,只在可用时获得更低能耗与更快触发。
    If the private invalidation path is unavailable because of macOS version, session state, or pboard daemon lifecycle, Deck keeps or restores adaptive polling; correctness does not depend on private APIs, while supported systems get lower power and faster triggers.

  • 升级前未持久化思考内容的旧会话
    若历史会话在升级前从未保存过 reasoning_content,极少数情况下思考模式模型仍可能报错;新开对话即可规避。
    Older chats that never stored reasoning_content before upgrade may still error in rare cases; starting a new conversation fully benefits from the fix.

升级建议 / Upgrade Notes

  • 使用思考模式或依赖 reasoning 回传时
    若遇到与 reasoning 相关的接口错误,优先新开对话;对关键旧线程可先验证一轮再长期使用。
    If you hit reasoning-related API errors, start a new chat first; verify critical legacy threads before relying on them.

  • 恢复过旧版 DB-only 备份后
    建议在确认记录列表正常后重新创建一次恢复备份,让新的 .bak.bak.blobs 成对保存,后续恢复会更完整。
    After restoring an old DB-only backup, create a fresh recovery backup once the list looks correct so the new .bak and .bak.blobs are saved together.