Claude Code Haha v0.3.0
这是一个围绕桌面端长会话性能、工具流式预览、AskUserQuestion 稳定性、多客户端流式订阅和 H5 网络可靠性的版本。
相比 v0.2.9,本次最核心的工作是对桌面端长会话进行了系统性的性能重构:从虚拟滚动稳定化、React 组件 memo 化、Markdown 缓存优化到跨 tab 高度缓存持久化,让 800+ 条消息的大会话在滚动和切换 tab 时不再出现白屏或卡顿。同时,流式 Writer 预览和 pending tool card 让长工具执行过程变得可感知,AskUserQuestion 和 IM 多端流式订阅的可靠性也得到了针对性修复。
Highlight
- 桌面端长会话滚动性能大幅提升:797+ 条消息 / 2.6MB 会话从 1-2s 白屏降低到 0s 白屏采样(34 个滚动位置全部通过)。通过稳定 1200px overscan、React 18 自动批处理、ResizeObserver 每帧批量回调和取消 scroll-handler 的 flushSync 实现。
- React 组件树 memo 化:AssistantMessage、UserMessage、ToolCallBlock 等 6 个重型组件加 React.memo;branchAction/toolResult 查找提升为 useMemo Map,窗口滑动时不变行跳过重渲染。
- Markdown 缓存重构:缓存 key 从完整内容字符串改为
${len}:${fnv1a}hash,拆分为 200 条 finalized(8MB)+ 4 条 streaming 缓存,streaming 不再驱逐已完成的 parse;VirutalSpacer 分片渲染,消除滚动白屏。 - 跨 tab 高度缓存持久化:新增 virtualHeightCache(按 sessionId 的模块级 LRU),切回已访问的 session 时复用历史测量高度,跳过 estimate→measure 校正过程;O(N) 的分支/完成计算改用 useDeferredValue 延后执行。
- 流式 Writer 预览和 pending tool card:长 Write 在 tool_use_start 时即渲染 pending 工具卡片,通过 delta 更新输入预览;Write.content 解码为轻量纯文本预览窗口,完成后保留完整 diff 渲染。
- AskUserQuestion 稳定性:CLI 的 toolUseResult 元数据在桌面 bridge 中不再丢失;重连时追踪并回放存活的 SDK 权限请求;自定义回答升级为多行编辑器(Ctrl/Cmd+Enter 提交)。
- 多客户端流式订阅:WebSocket handler 按客户端广播 session 消息,桌面端打开同一 session 不再"偷走" Telegram 的流内容;Telegram 长回答自动分块并累积 thinking delta。
- H5 内网链接更稳定:手动选择的 LAN 地址在 sidecar 端口变化后自动刷新为当前端口;手动 LAN host 不会被 WSL/Docker 虚拟网卡的自发现结果覆盖。
主要更新
桌面端长会话性能(6 个 commit 的系统性优化)
- 长对话切换为基于测量高度的动态虚拟窗口,短对话保持全量挂载;废弃 content-visibility 全列表覆盖方案以避免 WebView 白屏。
- 虚拟滚动 overscan 从动态膨胀(360px → 7200px)改为固定 1200px;移除 scroll-handler 的 flushSync,让 React 18 自动批处理接管状态更新。
- ResizeObserver 高度回调标记 pending bit 后,每帧仅触发一次 setMeasuredItemsVersion,而非每个 item 一次全列表重渲染;取消测量反馈的自动滚动,避免与用户滚动冲突。
- TabBar 的 chat-store 订阅收窄为 running-state ids,避免流式 payload churn 导致 tab chrome 无效重渲染。
- AssistantMessage、UserMessage、ToolCallBlock、ToolCallGroup、ToolResultBlock、MarkdownRenderer 全部加 React.memo;per-message 的 branchAction/toolResult 查找提升为 useMemo'd Map。
- Markdown 缓存 key 改为
${len}:${fnv1a}hash;200 条 8MB finalized cache + 4 条 streaming cache,streaming 期间不再禁用缓存;VirtualSpacer 将 spacer 切为 ~800px 分片,配合 content-visibility: auto + contain-intrinsic-size 消除白屏。 - virtualHeightCache(按 sessionId 的模块级 LRU)在 tab 切换时恢复历史高度和 metric map;关闭 tab 时通过 tabStore.closeTab → dropSession 释放缓存。getBranchableMessageTargets / getCompletedTurnTargets 改用 useDeferredValue(messages) 低优先级渲染。
工具流式预览
- tool_use_start 时 upsert 一个 pending tool_use 消息;delta 更新轻量输入预览;tool_use_complete 时原地更新为完整卡片,避免卡片重复。
- Write.content 在 pending 阶段解码为有界纯文本预览窗口,完成后保留现有完整 diff 渲染。
AskUserQuestion 可靠性
- CLI transcript 的 toolUseResult 结构化答案在 history replay 和 live WebSocket tool result 中保持一致传输,已回答卡片正确显示 resolved 状态。
- 追踪存活的 SDK permission request,重连时回放给新客户端;等待用户输入的 session 获得更长的清理宽限期;aborted 结果渲染为 completed history 而非未回答提示。
- 自定义回答输入框升级为多行编辑器,支持 Ctrl/Cmd+Enter 提交;修复历史恢复与 live permission request 重叠时出现重复未回答卡片的问题。
多客户端流式订阅
- WebSocket session output 改为按客户端追踪 callback,广播消息而非替换之前的订阅者;桌面端和 Telegram 可同时观察同一个流式 session。
- Telegram thinking delta 累积后编辑占位消息,而非每次用最新小块替换;长回答自动封存完整 chunk、打开新可编辑占位符,适配 Telegram 消息长度限制。
H5 内网链接
- 手动 LAN 地址 settings UI 支持分离 host/IP 输入,复用当前服务端口;不会被 WSL/Docker 虚拟网卡的自发现结果覆盖。
- 普通 HTTP 私有 LAN URL 在 sidecar 重启后自动刷新为当前动态端口;反向代理 URL 保持原样不动。
Worktree UI
- worktree session 的 desktop chip 隐藏内部分支标签(如 worktree-desktop-*)和 slug,仅显示源项目和 worktree 标记。
- git-info API 区分 launch branch 元数据和 worktree 实际 checkout 分支,session 进入 worktree 后才切换到实际分支。
其他改进
- OpenAI 代理流超时仅作用于建立上游连接阶段,不截断已开始的 SSE 生成。
- filesystem browser 注册已解析的 workspace root,支持 Windows 跨盘符项目(如 D:\workspace)的文件搜索。
- Computer Use 拒绝 Python 3.9 以下运行时,固定 Pillow 在 11.x 兼容线,配置镜像安装失败时 fallback 到默认 PyPI。
- Shiki 代码高亮改为懒加载,旧 WebKit 解析失败时 fallback 到 Prism,避免 macOS 12 WebView 启动崩溃。
问题修复
- 修复长会话滚动时 1-2s 白屏(flushSync 阻塞 compositor + 动态 overscan 膨胀 + ResizeObserver 大量同步重渲染)。
- 修复虚拟滚动 spacer 大块 div 导致 WebView 无内容可绘制、出现滚动白屏。
- 修复 Markdown 缓存用完整内容字符串做 key 导致大会话频繁驱逐、streaming chunk 驱逐已完成解析。
- 修复窗口滑动时每行都从零重渲染(无 memo 屏障 + 每次 render 重建 object literal)。
- 修复 tab 切换回已访问 session 时高度和 metric map 被清空,强制 estimate→measure 全程校正。
- 修复长 Write 工具调用在 tool_use_complete 之前不显示任何可见进度的问题。
- 修复 AskUserQuestion 回答后仍显示为未解决、历史恢复出现重复卡片、重连导致 CLI 被 AbortError 杀死。
- 修复桌面端打开同一 session 后 Telegram 丢失流内容和 completion 事件。
- 修复 Telegram 长回答超过消息长度限制后停止更新、thinking delta 每次用最新小块替换导致预览回缩。
- 修复 H5 内网链接在 sidecar 重启后保留过期端口、手动 LAN host 被自发现覆盖。
- 修复 OpenAI 代理流被全请求超时截断,长 SSE 生成中途停止。
- 修复 worktree session 显示 source branch 或内部 ref 标签(worktree-desktop-*)。
- 修复 Windows 跨盘符项目在 filesystem browser 中无法搜索文件。
- 修复 desktop compact 状态在 auto-compact 或取消后卡住不消失。
- 修复 Computer Use 在低版本 Python 环境安装依赖失败。
- 修复旧版 Safari/WebKit 解析 Shiki 现代 RegExp 语法导致启动崩溃。
验证
- 桌面端性能相关 commit 有 5 个新增的 virtualHeightCache 测试用例和 4 个 markdown-cache + spacer-chunk 回归测试;全套 731 desktop vitest suite 保持通过。
- Chrome DevTools trace 在真实 797 消息 session 上验证:tab 切换 max RunTask 约 158ms,滚动 34 个位置 blankSamples=0,INP 从 84ms 降到 43ms,ForcedReflow insight 消失。
- AskUserQuestion 相关变更已通过 desktop chatStore、MessageList、AskUserQuestion 组件测试和 server sessions、ws-memory-events 测试。
- H5 相关变更已通过 h5-access-service、h5-access-api、h5-access-auth、h5-access-policy 全套测试。
- Computer Use 相关变更已通过 computer-use-api、computer-use-requirements、computer-use-python、pipInstall 测试。
- 各功能分支已分别跑过 targeted server / desktop / adapters 测试;
v0.3.0发布前建议再跑一次bun run verify,并在真实长会话(800+ 消息)上补一次 scroll + tab 切换 smoke。
其他说明
- GitHub Release 正文继续以
release-notes/v0.3.0.md作为来源,发布时无需手动复制 Markdown。 - 桌面端性能优化涉及虚拟滚动、React memo、缓存和 layout 路径变更;升级后如果遇到滚动异常或高度计算问题,通常是测量缓存或 spacer 分片与特定 WebView 版本的兼容问题,请反馈具体 session 大小和 WebView 版本。
- 流式 Writer 预览和 pending tool card 依赖 provider 正确发送 tool_use_start 和 input delta 事件;如果 provider 仅发送 tool_use_complete,pending 卡片不会出现但最终卡片照常渲染。
- 本版本包含大量桌面端渲染和 layout 路径变化,建议在 macOS WebKit、Windows WebView2 和 Linux WebKitGTK 三个平台上各做一次真实长会话滚动 + tab 切换 smoke。
安装说明
macOS
首次打开如果提示"已损坏"或"无法验证开发者",请执行:
:::bash
xattr -cr /Applications/Claude\ Code\ Haha.app