fix(packaging): restore clipboard image paste in standalone builds - #6708
Conversation
|
Thanks for the PR, @zjunothing! Template looks good ✓ — all required sections present, bilingual, evidence included. Problem: This is an observed bug with a linked issue (#6590). On macOS standalone builds, Direction: Aligned. Clipboard image paste is a user-facing feature that should work across all installation methods. CHANGELOG shows the same pattern was already applied for the audio native addon (#5628 — Size: No core paths ( Approach: The two-part solution — (1) stage lockfile-pinned clipboard packages and include only the target-matching variant in each archive, (2) show one actionable TUI error per session when the native module can't load — feels right-sized. The promise-based caching refactor in Moving on to code review. 🔍 中文说明感谢贡献,@zjunothing! 模板完整 ✓ — 所有必需章节齐全,双语,包含证据。 问题: 这是一个已观测到的 bug,关联 issue #6590。在 macOS standalone 构建中, 方向: 对齐。剪贴板图片粘贴是用户可见的功能,应在所有安装方式下正常工作。CHANGELOG 中已有相同模式的先例(#5628 — 将音频原生 addon 打包到 standalone 归档),剪贴板支持也有前例(#4929 — OSC 52 剪贴板回退)。这是对已有工作的自然补全。 规模: 未触及核心路径( 方案: 两部分方案——(1) 暂存锁文件固定版本的剪贴板包,每个归档只包含对应目标的变体;(2) 原生模块加载失败时,每个会话在 TUI 中显示一次可操作的错误——范围恰当。 进入代码审查 🔍 — Qwen Code · qwen3.7-max |
E2E Test Report — PASSEnvironment
Baseline reproduction
Patched standalone verification
Cross-target and automated verification
The image below is rendered from the two real tmux captures; only the comparison labels were added. 中文验证报告E2E 测试报告 — 通过环境
基线复现
修复版 standalone 验证
跨目标与自动化验证
下图由两次真实 tmux 捕获渲染而成,只额外添加了对比标签。 |
Code ReviewIndependent proposal (before reading the diff): Given "clipboard image paste fails silently in standalone builds because Comparison: The PR matches this almost exactly, and goes further in good ways:
No critical blockers found. The diff is focused — every change serves the stated goal. The No AGENTS.md violations. The code is straightforward, follows existing patterns, and adds tests alongside the implementation. Unit TestsAll four affected test suites pass:
New tests cover: cached load failure notification, concurrent load sharing, one-time error across remounts, empty-paste unavailable reporting, target→clipboard package mapping, per-archive addon inclusion, and incomplete staging rejection. Real-Scenario TestingBuild and dev-run on Linux CI. The clipboard image paste feature uses After (PR dev build)CLI starts, responds, exits cleanly. No regressions visible. The macOS clipboard scenario requires real macOS hardware to verify end-to-end — the author's test plan in the PR body covers this with a real macOS arm64 standalone archive. 中文说明代码审查独立方案(在阅读 diff 之前):鉴于"standalone 构建中剪贴板图片粘贴静默失败,因为 对比: PR 与我的方案几乎一致,并且在一些地方做得更好:
未发现关键阻塞问题。 diff 聚焦——每个变更都服务于既定目标。无安全问题,无回归。 单元测试四个受影响的测试套件全部通过:clipboardUtils 29/29、KeypressContext 99/99、InputPrompt 185/185、install-script 110/110(9 个跳过)。 真实场景测试在 Linux CI 上构建并运行 dev build。剪贴板图片粘贴在 Linux 上使用 — Qwen Code · qwen3.7-max |
|
This is a clean, well-executed fix for a real user-facing bug. The problem is clearly observed (issue #6590, clipboard image paste silently fails on standalone macOS builds), the root cause is correctly identified (native addon not bundled in The implementation is straightforward: stage the lockfile-pinned clipboard packages, include only the target-matching variant in each archive, and show a one-time error when the module still can't load. The promise-based caching refactor is a genuine improvement over the boolean-flag approach for concurrent safety. Every change in the diff serves the stated goal — no scope creep, no drive-by refactors. All 323 unit tests across the four affected suites pass. The dev build starts and responds normally on Linux. The macOS-specific scenario requires real hardware to verify end-to-end, which the author has already done (evidence in the PR body). The approach matches what I'd propose independently, and the execution is solid. LGTM. 中文说明这是一个干净、执行良好的修复,解决了一个真实的用户可见 bug。问题已明确观测(issue #6590,macOS standalone 构建上剪贴板图片粘贴静默失败),根因正确识别(原生 addon 未打包到 实现简洁:暂存锁文件固定版本的剪贴板包,每个归档只包含对应目标的变体,模块加载失败时显示一次性错误。基于 Promise 的缓存重构对并发安全是真正的改进。diff 中的每个变更都服务于既定目标——无范围蔓延,无顺手重构。 四个受影响套件的全部 323 个单元测试通过。dev build 在 Linux 上正常启动和响应。macOS 特定场景需要真实硬件端到端验证,作者已完成(证据在 PR 正文中)。 方案与我独立提出的方案一致,执行扎实。LGTM。 — Qwen Code · qwen3.7-max |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
No issues found. LGTM! ✅
— qwen3.7-max via Qwen Code /review
✅ Maintainer local verification — merge referenceI built and ran this PR locally against real artifacts. Summary: all tests green on the PR, all new tests genuinely fail without it, and the real standalone archive bundles a loadable clipboard native. Recommendation: good to merge. Environment: macOS 15.7.7 arm64 · Node v22.23.1 · npm 10.9.8 · PR head 1) Tests + before/after
To make the before/after honest I overlaid the parent commit's source into the 7 changed files while keeping the PR's tests, then re-ran: they fail with 2) Real end-to-end packaging (real npm artifacts, not fakes)
Notes / scope
中文说明(点击展开)✅ 维护者本地验证 —— 合并参考我在本地基于真实产物构建并运行了本 PR。结论:PR 上所有测试通过;去掉本 PR 改动后这些新测试全部失败;真实的 standalone 归档确实打包了一个可加载的剪贴板原生模块。 建议:可以合并。 环境: macOS 15.7.7 arm64 · Node v22.23.1 · npm 10.9.8 · PR head 1)测试 + 前后对比(第一张图)
为保证前后对比真实可信,我把父提交的源码覆盖回这 7 个改动文件、但保留 PR 的测试后重跑:出现 2)真实端到端打包(真实 npm 产物,非 mock,第二张图)
备注 / 范围
Verification run in an isolated worktree on real hardware; screenshots are faithful renders of the actual command output (transcribed, not fabricated). |



What this PR does
Standalone release builds now stage the lockfile-pinned clipboard meta package and all supported native variants once, then include only the variant matching each archive target. Explicit release staging fails closed when a required artifact is missing, while local packaging keeps its existing best-effort behavior.
If the native clipboard module still cannot load on macOS or Windows, the TUI now shows one actionable error per session instead of failing silently. The same behavior covers direct clipboard shortcuts and empty bracketed-paste events, and concurrent load attempts share one result.
Why it's needed
Standalone archives externalize clipboard support but previously shipped without its runtime package, so pasting a clipboard image did nothing even though npm installations worked. Users also received no visible explanation because the load failure was only written to the debug log.
Reviewer Test Plan
How to verify
Evidence (Before & After)
Tested on
Environment (optional)
macOS arm64, official Node.js 22.23.1 darwin-arm64 runtime, real macOS system clipboard, standalone archive extracted under
/private/tmp, and tmux-driven TUI input. Cross-target npm staging was also exercised from macOS and retained all five target-native packages.Risk & Scope
Linked Issues
Fixes #6590
中文说明
本 PR 做了什么
Standalone 发布构建现在会一次性暂存锁文件固定版本的剪贴板主包和所有受支持平台的原生变体,然后只把与每个归档目标匹配的变体放入对应归档。显式发布暂存缺少必需制品时会直接失败,而本地打包仍保持原有的尽力而为行为。
如果原生剪贴板模块在 macOS 或 Windows 上仍然无法加载,TUI 现在会在每个会话中显示一次可操作的错误,不再静默失败。直接剪贴板快捷键和空的 bracketed-paste 事件都使用相同行为,并发加载也会共享同一个结果。
为什么需要
Standalone 归档把剪贴板支持保留为外部依赖,但此前没有携带运行时包,因此粘贴剪贴板图片不会产生任何结果,而 npm 安装方式正常。由于加载失败只写入调试日志,用户也看不到任何解释。
评审测试计划
如何验证
证据(修复前后)
已测试平台
环境(可选)
macOS arm64、官方 Node.js 22.23.1 darwin-arm64 运行时、真实 macOS 系统剪贴板、在
/private/tmp下解压的 standalone 归档,以及通过 tmux 驱动的 TUI 输入。还在 macOS 上实测了跨目标 npm 暂存,全部五个目标平台的原生包均被保留。风险与范围
关联 Issue
Fixes #6590